naftoli@aecom.UUCP (Robert Berlinger) (11/02/83)
There seems to be a slight ambiguity in the description of external variables in the C reference manual. (The C programming language, Kernighan & Ritchie, Prentice Hall 1978). To my knowledge the proper way to declare a global variable is to declare "int foo;" in one source file and declare "extern int foo;" in all the rest. However, according to the reference manual this seems unnecessary and you should be able to declare "int foo;" in all source files. The reference page 205, paragraph 10.2 states: > 10.2 External data definitions > An external data definition has the form > > data-definition: > declaration > > The storage class of such data may be extern (which is the > default) or static, but not auto or register. According to this, since data outside of a procedure is by default extern, you need not ever explicitly declare it as such. This is true in the case of most UN*X compilers that I've seen. Example: file 1: int foo = 8; file 2: int foo; No errors; foo will be initialized to 8. file 1: int foo; file 2: int foo = 8; No errors; foo will be initialized to 8. file 1: int foo = 8; file 2: int foo = 7; Multiply defined error from loader. file 1: extern int foo; file 2: extern int foo; Undefined _foo message from loader. file 1: extern int foo = 8; Compiler msg - cannot initialize external. The last two errors are the most important here. If extern is purported to be the default, then why do you get an error if you state it explicitly? Also, I've heard that IBM/370 compilers do not resolve the references and will create two seperate global cells. If this is true (that not all compilers resolve several global declarations) then the reference manual should not say that extern is the default. Rather, a null storage class outside of the program definition should mean declaration, and an extern storage class should mean definition. Robert Berlinger Systems Support Albert Einstein Coll. of Med. {philabs,esquire,cucard}!aecom!naftoli
john@genrad.UUCP (John Nelson) (11/02/83)
There's no ambiguity here, any compiler that acts that way is WRONG!!!! file 1: extern int foo; file 2: extern int foo; This should not generate a loader error, The loader is SUPPOSED to allocate storage for foo. Unfortunately, sometimes C running under operating systems other than UNIX use the existing loader, which does not perform this function. file 1: extern int foo = 8; If the compiler generates an error on this, then it is just plain WRONG! I cannot emphasize this enough. The problem is not that the reference manual should not say that extern is the default storage class, it IS, and any compiler that does not work this way is not strictly C! I had a similar problem with the Whitesmith compiler - all externs had to be initialized (which could be lived with) but also, static's had to be initialized! If you have: file 1: static int foo; you get the compiler message: "undeclared static foo". We don't use Whitesmiths anymore for this and numerous other non-standard items.
keesan@bbncca.ARPA (Morris Keesan) (11/02/83)
The key to the apparent ambiguity is found on the following page (p. 206) of Kernighan & Ritchie, in section 11.2, entitled "Scope of externals". I quote: If a function refers to an identifier declared to be extern, then somewhere among the files or libraries cnstituting the complete program there must be an external definition for the identifier. . . . The appearance of the extern keyword in an external definition indicates that strage for the identifiers being declared will be allocated in another file. Thus in a multi-file program, an external data definition without the extern specifier must appear in exactly one of the files. Any other files which wish to give an external definition for the identifier must include the extern in the definition. The identifier can be initialized only in the declaration where storage is allocated. Thus, there is no real ambiguity, and though the storage class of both types of definition is extern, the distinction is between a definition which reserves space and one which doesn't. It is then obviously incorrect for there to be two declarations without the extern keyword, since space is being reserved twice, but most compilers/loaders should be able to handle the case where all the declarations for an external identifier have the extern keyword, by recognizing the special case of an undefined external, and allotting space for it, similar to the way Fortran COMMONs are handled when there is no BLOCK DATA subprogram for them.
keesan@bbncca.ARPA (Morris Keesan) (11/03/83)
----- This note is to disagree strongly with John Nelson (genrad!john). I quote alternately from his message and the "C Reference Manual", Appendix A of "The C Programming Language", which I take to be the final arbiter of what is and isn't "strictly C". Nelson: ------- > file 1: extern int foo; > file 2: extern int foo; > >This should not generate a loader error, The loader is SUPPOSED to >allocate storage for foo. ----- The loader is NOT supposed to allocate storage, as per Kernighan and Ritchie, p. 206: ----------------------------- The appearance of the extern keyword in an external definition indicates that storage for the identifiers being declared will be allocated in another file. Thus in a multi-file program, an external data definition without the extern specifier must appear in exactly one of the files. ----------- Nelson: ------- > file 1: extern int foo = 8; > >If the compiler generates an error on this, then it is just plain WRONG! >I cannot emphasize this enough. The problem is not that the reference >manual should not say that extern is the default storage class, it IS, >and any compiler that does not work this way is not strictly C! ----------- When the compiler generates an error on the above, it is behaving RIGHT, as evidenced by the sentence in Kernighan & Ritchie immediately following the previous citation. Kernighan and Ritchie, also p. 206: ----------------------------------- The identifier can be initialized only in the declaration where storage is allocated. ---------- Nelson: ------- >I had a similar problem with the Whitesmith compiler - all externs had to >be initialized (which could be lived with) but also, static's had to be >initialized! If you have: > > file 1: static int foo; > >you get the compiler message: "undeclared static foo". We don't use >Whitesmiths anymore for this and numerous other non-standard items. ---------- Here I share John Nelson's complaint. The C compiler for Charles River Data Systems' UNOS system also requires explicit initialization of statics, in direct violation of Kernighan & Ritchie, p. 198: "Static and external variables which are not initialized are guaranteed to start off as 0;"
john@genrad.UUCP (John Nelson) (11/03/83)
GREAT HORNY TOADS! I was wrong! I stand corrected.
/~\
(o o)
| O | John
\v/
/---\
notes@ucbcad.UUCP (11/03/83)
#R:aecom:-22300:ucbesvax:4800030:000:355 ucbesvax!turner Nov 3 02:53:00 1983 Re: john@genrad's comments. > cat t.c extern int foo; main() { printf ("%d\n", foo); } > cat t1.c extern int foo; f(){} > cc t.c t1.c t.c: t1.c: Undefined: _foo {~ Golly, I guess 4.2bsd cc is just plain WRONG WRONG WRONG. ~} John, please reread K&R. I don't think your inference is correct. --- Michael Turner (ucbvax!ucbesvax.turner)