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) browngwyn@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!
--davekvm@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.