DBrown@Hi-Multics.ARPA (03/29/84)
From: Dave Brown <DBrown@Hi-Multics.ARPA> There is a difficulty (I won't call it a bug) with the understanding that PCC and Lint have of what "extern" and "static" mean. We have several programs obtained from a Vax site which contain code like: <beginning of file> main () { extern int proc1(); ... proc1(); ... } static proc1() { ... } <end of file> PCC and Lint notice the "extern" declaration and remember that the author has warned them that they may have to issue an external reference. They then find the procedure in the file, decide that they can link it without issuing an external ref for LD, and quite properly do so. Unfortunatly, at this point they seem to have lost track of the fact that the first declaration asserted something that wasn't true: it claimed that proc1 was a "normal" external function. We now see that proc1 isn't a normal external, but instead is a "static" (meaning private) function. To quote the white book, ".. static variables and functions provide a way to conceal data objects and any internal routines that manipulate them so that other routines and data cannot conflict even inadvertantly." For obvious reasons we prefer to have the function declared the same way (as static) every time, and have redeclared it that way so Lint won't complain so loudly. This raises two questions: (1) Does anyone have a compiler which DEMANDS statics be predeclared as externs? (ie, can we fix the code without making that a machine- or compiler-specific fix), and (2) Are the Unix(tm) compilers and Lint correct in accepting this construct or should they be regarding this as a legal but non-portable construct? --dave (unix hack on a bun) brown There is a difficulty (I won't call it a bug) with the understanding that PCC and Lint have of what "extern" and "static" mean. We have several programs obtained from a Vax site which contain code like: <beginning of file> main () { extern int proc1(); ... proc1(); ... } static proc1() { ... } <end of file> PCC and Lint notice the "extern" declaration and remember that the author has warned them that they may have to issue an external reference. They then find the procedure in the file, decide that they can link it without issuing an external ref for LD, and quite properly do so. Unfortunatly, at this point they seem to have lost track of the fact that the first declaration asserted something that wasn't true: it claimed that proc1 was a "normal" external function. We now see that proc1 isn't a normal external, but instead is a "static" (meaning private) function. To quote the white book, ".. static variables and functions provide a way to conceal data objects and any internal routines that manipulate them so that other routines and data cannot conflict even inadvertantly." For obvious reasons we prefer to have the function declared the same way (as static) every time, and have redeclared it that way so Lint won't complain so loudly. This raises two questions: (1) Does anyone have a compiler which DEMANDS statics be predeclared as externs? (ie, can we fix the code without making that a machine- or compiler-specific fix), and (2) Are the Unix(tm) compilers and Lint correct in accepting this construct or should they be regarding this as a legal but non-portable construct? --dave (unix hack on a bun) brown
gwyn@Brl-Vld.ARPA (03/30/84)
From: Doug Gwyn (VLD/VMB) <gwyn@Brl-Vld.ARPA> CC and LINT are behaving properly in regard to "extern" declaration of a function in the same file as a "static" definition. The use of "extern" and "static" has evolved through the years but the current meaning has been around for a while. The only remaining debate seems to be about multiple extern definitions (not declarations), which were put back into UNIX System V Release 2 because of complaints from sites that had sloppy code that they didn't want to fix (so I am told). At least they also added an option to the loader so we can still get the warnings if we want them. Keep in mind that "extern" has AT LEAST three different meanings. In proc() { extern type func(); ... it basically means "import". Using "static" in this context should generate an error. Since you get the same meaning in this case without the "extern" qualifier, it is really just a noise word in this context. Sorry about that, but let's not try to change the language at this point...
DBrown.CSC_SDO@Hi-Multics.ARPA (04/03/84)
Hmmn...
Well, I did phrase that as if I wanted to say "static int foo()"
inside a function, didn't I.
Perhaps the question should be: can I say
main() {
char *p, *capitalize_names();
...
}
static char *capitalize_names(q) char *q; {
...
without *either* static or extern declarations.
My lint (not unexpectedly) gets upset when I tell it that a function
is both static and external. I would not expect it to complain if I say
something is "function returning char pointer" and later add the fact
that it's "static".
So I'll reask the question: does anyone have a compiler which
*requires* a static be declared extern?
If they do I'll conclude dropping the "extern" in my declaration is
non-portable.
If they don't, I'll conclude that the use of extern ::= static is the
non-portable construct.
IN EITHER CASE I CONCLUDE AND PROPOSE THAT THE CONSTRUCT IS LEGAL C,
since at least one standard-conforming C compiler allows it.
I like C as it stands, too!
--dave
kvm@basser.SUN (Karlos Mauvtaque) (04/04/84)
no "extern" always means "externally visible". extern int i; declares an externally visible int with name i, it doesn't matter where the declaration appears. remember, the default storage class is "extern" (section 10.2 of the C reference manual) so this is equivalent to int i; similarly extern int poot(); or int poot(); declares an externally visible function returning int named poot, the absence of a function body requires that one appear elsewhere. the ambiguity is in the C compilers which float around. some compilers adopt the "restricted environment" (where the explicit appearance of "extern" means that storage is allocated elsewhere), some just do incorrect things.
qwerty@drutx.UUCP (JonesBD) (04/06/84)
I would take exception to your statement that extern int i; and int i; are equivalent, in that the first declaration reserves no storage for the variable 'i', while the second declaration does reserve storage for the variable 'i'. The extern declaration tells the compiler that storage for the variable 'i' will be allocated in another module.
chris@basser.SUN (Chris Maltby) (04/08/84)
x My copy of the C Reference Manual quite clearly states in section 10. "A C program consists of a sequence of external definitions. An external definition declares an identifier to have storage class 'extern' (by default) or perhaps 'static'..." If your C compiler doesn't do that, then it's WRONG (like most UN*X C compilers). Just because your loader is correspondingly broken is no reason to assume that you have some alternative standard. Can the discussion of this rest now. Chris Maltby University of Sydney
kvm@basser.SUN (Karlos Mauvtaque) (04/12/84)
<reschs refreshes> > IN EITHER CASE I CONCLUDE AND PROPOSE THAT THE CONSTRUCT IS LEGAL C, > since at least one standard-conforming C compiler allows it. So we take all of the bugs in PCC to be legal C? Try this: main() { int (*f)(); (*f)(); (**f)(); f(); (******f)(); } What piffle.