robert@gitpyr.UUCP (Robert Viduya) (01/18/85)
[] The other day I was modifying some source code when I came across something that showed me one of the limitations of the sizeof operator. Basically, I had the following in a source file: extern struct s a[]; . . . b = sizeof(a); . . Needless to say, the compiler assigned 0 to b instead of the actual size of the array. Obviously, in order to handle things like this, C needs a runtime version of sizeof. I can see two ways of doing this. One way is to have the size of each variable stored as part of that variable (waste a bit of storage). Another way is to implement it as a real function that 'knows' where all the variables are and can compute the size of each (also can waste storage). A third way, which I see to be the best, is to defer the evaluation of any sizeof operation that references an external value to link/load time and put a placeholder in its place. The linker/loader would have to replace the placeholder with the actual size of the external variable (since it knows the size anyway). This doesn't waste any unnecessary storage for 'hidden' variables and also allows using the sizeof operator with external variables. Comments anybody? robert -- Robert Viduya Office of Computing Services Georgia Institute of Technology, Atlanta GA 30332 Phone: (404) 894-4669 ...!{akgua,allegra,amd,hplabs,ihnp4,masscomp,ut-ngp}!gatech!gitpyr!robert ...!{rlgvax,sb1,uf-cgrl,unmvax,ut-sally}!gatech!gitpyr!robert
robert@gitpyr.UUCP (Robert Viduya) (01/20/85)
[]
Judging from mail I've recieved about the subject, I think I was a bit
unclear about the problem. This should clear things up.
The problem is that the sizeof operator produces different answers
when used in two different source files. I can declare the following
in one source file:
...
struct s a[] = {
{ "....",0,0,0 },
{ ",,,,",1,1,1 },
};
...
b = sizeof (a);
and have b be set to some number representing the size of a in bytes, but
I cannot refer to the same structure from another source file:
...
extern struct a[];
...
b = sizeof (a); /* set to zero or a compiler error msg */
The array is defined and initialized to contain data. Therefore, the
sizeof operator should work *regardless* of what source file it is used in.
robert
--
Robert Viduya
Office of Computing Services
Georgia Institute of Technology, Atlanta GA 30332
Phone: (404) 894-4669
...!{akgua,allegra,amd,hplabs,ihnp4,masscomp,ut-ngp}!gatech!gitpyr!robert
...!{rlgvax,sb1,uf-cgrl,unmvax,ut-sally}!gatech!gitpyr!robert
guy@rlgvax.UUCP (Guy Harris) (01/21/85)
> A third way, which I see to be the best, is to defer the evaluation of any > sizeof operation that references an external value to link/load time and put > a placeholder in its place. The linker/loader would have to replace the > placeholder with the actual size of the external variable (since it knows > the size anyway). This doesn't waste any unnecessary storage for 'hidden' > variables and also allows using the sizeof operator with external variables. Nice, except that there's a lot more to this than just giving the linker the ability to do a "sizeof". Take, for example, a = sizeof(b)*2 + 3; If "b" were an "extern" array with an empty dimension specifier, so that this constant would have to be evaluated at link time, the linker would have to be able to perform arbitrary computations. There are several linkers which can do this (the DEC PDP-11 and VAX linkers among them), but to make the UNIX linker handle this you'd not only have to add a "sizeof" operator to the linker but add the ability to do this sort of "complex relocation" as well. Guy Harris {seismo,ihnp4,allegra}!rlgvax!guy
greenber@acf4.UUCP (ross m. greenberg) (01/28/85)
<> What I always have is a little .h file: = = = = = = = = = = = #ifndef NULL #define NULL (int) 0 #endif #ifndef NULLP #define NULLP (char *)NULL #endif = = = = = = = = = = = Aside from being "portable", it really makes code easier to read because you know which are apples and which are pears. I also go the whole way with additional NULLs defined (NULLL, NULLS, NULLD, NULLF, etc.), because this won't always work: long var; if (var == NULL) {stuff} Then of course the question is, will this work: long var; if (var) {stuff} I've found that it doesn't always (flaky compilers!), so I have made my code (when needed): long var; if (var != NULLL) {stuff} Sloppy, but portable!!! (and easy to understand, even for me!) Didn't we have this discussion about three months ago?? ------------------------------------------------------ Ross M. Greenberg @ NYU ----> { allegra,ihnp4 }!cmcl2!acf4!greenber <----
bsa@ncoast.UUCP (Brandon Allbery) (02/06/85)
As to the null pointer controversy, I've taken to using a derivative of the technique Larry Wall uses in rn for all but the quick, sloppy ultra-local (TRS-Xenix) programs: #define Null(type) ((type *) 0) ... if ((fp = fopen(filename, "r")) == Null(FILE)) ... You get the idea. Easy to use and it makes the point (pun not intended) evident. --bsa -- Brandon Allbery @ decvax!cwruecmp!ncoast!bsa (..ncoast!tdi1!bsa business) 6504 Chestnut Road, Independence, Ohio 44131 +1 216 524 1416 (or what have you)
guy@rlgvax.UUCP (Guy Harris) (02/11/85)
> #define Null(type) ((type *) 0) > > ... > if ((fp = fopen(filename, "r")) == Null(FILE)) > ... > > You get the idea. Easy to use and it makes the point (pun not intended) > evident. Although it isn't necessary; the compiler knows that the LHS of the "==" is a "FILE *" so it can coerce the "0" to a null FILE *. In ANSI Standard C it can even be told that the Nth argument to a function is a FILE * and will coerce 0 there; the only place this doesn't work is in functions which take a variable number of arguments. The main "offender" here is "execl", which is just a bit of syntactic sugar - anything you can do with "execl" you can do with "execv" at the expense of having to build an argument vector somewhere else. Guy Harris {seismo,ihnp4,allegra}!rlgvax!guy