jimpr@tekcbi.UUCP (10/01/85)
A C compiler we are using was designed in such a way that the following code would not compile: extern int thing; /* don't know yet if thing is static or not */ main() { printf("%d %d\n", thing, increment(thing)); } static int thing = 0; /* now we know that it's static */ int increment(x) int x; { return(++x); } Now the situation is basically this: the compiler complains because "thing" is first declared external int, referenced (as extern int) and then declared (the designers say "re-declared") static int after the reference. Their contention that not allowing this type of forward referencing of static variables is consistent with "The C Programming Language", (K. & P.). Now I know this program works quite well on our VAX running 4.2BSD, our Pyramid running 4.2BSD & System V, and other users say that a few PC's running Microsoft C and Lattice C are quite happy with this construction. They all make "thing" static (ie, local to the file "thing" is defined in). What say you all? Is there any language in K & P which would dissuade them? Thanks! --Jim Prouty Tektronix, Inc uucp: {ucbvax,decvax,pur-ee,ihnss,chico}!tektronix!tekcbi!jimpr ARPAnet: tekcbi!jimpr.tek@rand-relay CSnet: tekcbi!jimpr@tek
gwyn@BRL.ARPA (VLD/VMB) (10/04/85)
extern int thing; ... static int thing = 0; is perfectly legitimate according to X3J11. Why waste time trying to relate this to K&R (not K&P). Point out to your compiler supplier that they're going to have to fix this anyway.
friesen@psivax.UUCP (Stanley Friesen) (10/04/85)
In article <365@tekcbi.UUCP> jimpr@tekcbi.UUCP writes: >A C compiler we are using was designed in such a way that the following >code would not compile: > > extern int thing; /* don't know yet if thing is static or not */ . . . > static int thing = 0; /* now we know that it's static */ > >Their contention that not allowing this type of forward referencing of >static variables is consistent with "The C Programming Language", (K. & P.). > (Various other compilers are mentioned) >They all make "thing" static (ie, local to the file "thing" is defined in). > >What say you all? Is there any language in K & P which would dissuade them? >Thanks! > Well, I cannot find anything explicit in K&R, but the ANSI Draft Standard fairly clearly indicates that this *is*(or will be) legal. So any compiler which wants to conform th the std will have to accept this construct. -- Sarima (Stanley Friesen) UUCP: {ttidca|ihnp4|sdcrdcf|quad1|nrcvax|bellcore|logico}!psivax!friesen ARPA: ttidca!psivax!friesen@rand-unix.arpa
doug@terak.UUCP (Doug Pardee) (10/04/85)
From K&R Appendix A: 11.2 Scope of externals If a function refers to an identifier declared to be extern then somewhere... there must be an external [as opposed to static -- dlp] definition for the identifier. ... The appearance of the extern keyword in an external definition indicates that storage for the identifiers being declared will be allocated in another [as opposed to the current -- dlp] file. 11.1 Lexical scope The lexical scope of identifiers declared in external definitions persists from the definition through the end of the source file in which they appear. The problem here is that an "extern" declaration tells the compiler that the address for the data item (or function) will be supplied by the link-editor when the program is linked; but the "static" declaration tells the compiler that the address is "private information" to the current module. A system which is smart in this regard could provide a method for the link-editor to be told that a given address is to be used only within the current module. But many systems aren't that "smart" -- it's only useful for this one case. A simpler approach is usually used: the link-editor just isn't told about static variables. -- Doug Pardee -- CalComp -- {calcom1,savax,seismo,decvax,ihnp4}!terak!doug
bc@cyb-eng.UUCP (Bill Crews) (10/05/85)
> extern int thing; > ... > static int thing = 0; > > is perfectly legitimate according to X3J11. > Why waste time trying to relate this to K&R (not K&P). > Point out to your compiler supplier that they're > going to have to fix this anyway. I know you're always (usually?) right, Doug, but this seems to me to be an ambiguity. One might have the symbol 'thing' defined in another module to be linked with this one, and a reference to 'thing' that appears between the above 'extern' and 'static' might be thought to refer to the external symbol, since the scope of a static is from the definition point through the end of the block or source file, depending upon where it is defined. Not so? -- / \ Bill Crews ( bc ) Cyb Systems, Inc \__/ Austin, Texas [ gatech | ihnp4 | nbires | seismo | ucbvax ] ! ut-sally ! cyb-eng ! bc
meissner@rtp47.UUCP (Michael Meissner) (10/05/85)
In article <1893@brl-tgr.ARPA> gwyn@BRL.ARPA (VLD/VMB) writes: >extern int thing; >... >static int thing = 0; > >is perfectly legitimate according to X3J11. >Why waste time trying to relate this to K&R (not K&P). >Point out to your compiler supplier that they're >going to have to fix this anyway. > Sorry that is wrong. The only thing that ANSI X3J11 allows is: static int thing = 0; foo(){ float thing; /*...*/ { extern int thing; /* refers to static above */ } } Ie, the first declaration MUST be static. Michael Meissner, Data General, ...{ihnp4, decvax}!mcnc!rti-sel!rtp47!meissner
brooks@lll-crg.ARpA (Eugene D. Brooks III) (10/05/85)
extern int thing;
static int thing = 3;
main()
{
int thing = 5;
}
Where is the ambiguity now?
gwyn@BRL.ARPA (VLD/VMB) (10/06/85)
Actually, I no longer remember why I thought that
extern int thing;
...
static int thing = 0;
is legal (according to X3J11). My reading today is
that the first declaration gives "thing" external
linkage and the second declaration gives it static
linkage, which is a contradictory declaration. I
think I must have missed the description of linkage
in the X3J11 document when I first looked this up.
My current position is that this is NOT legal usage.
Sorry for the mistake; thanks for pointing it out.
Minow sent me another illustration:
func() {
extern char *foo();
...
}
...
static char *foo() { ... }
which my latest attempt at understanding X3J11
tells me is illegal, since without a file-scope
definition in effect, the "extern" forces external
linkage whereas the "static" specifies static
linkage. In this case, adding
static char *foo();
at the front of the file will keep the "extern"
from having an effect on the linkage type.
K&R is not nearly as thorough in this whole area
as the X3J11 specification, although X3J11 seems
to be compatible with the intent of K&R.
Needless to say, there are a number of compilers
around today that do not enforce these rules.
Programmers: Declare everything before you use it.
If it is a file-static (private) object/function,
call it "static" whenever you declare it. If it is
an external (public) object/function, not defined in
the same file, call it "extern". If it is external
but defined in the same file, you may call it
"extern" in all declarations other than the defining
one. Don't call anything both "extern" and "static".
(X3J11 is actually more complex than this, but these
rules should keep you out of trouble.)
savage@ssc-vax.UUCP (Lowell Savage) (10/08/85)
> A C compiler we are using was designed in such a way that the following > code would not compile: > extern int thing; /* don't know yet if thing is static or not */ > main() {...} > static int thing = 0; /* now we know that it's static */ > int increment(x)... > Now the situation is basically this: the compiler complains because > "thing" is first declared external int, referenced (as extern int) and > then declared (the designers say "re-declared") static int after the > reference. > > Their contention that not allowing this type of forward referencing of > static variables is consistent with "The C Programming Language", (K. & P.). > What say you all? Is there any language in K & P which would dissuade them? > Thanks! > --Jim Prouty Tektronix, Inc From the way I read K&R, the "static" keyword is redundant, unless it is inside a function. In other words, "static int thing;" is equivalent to "int thing;" unless the declaration takes place inside a function. (Any comment on that??) Then, the "extern" keyword specifies that the variable declared is contained in some other program unit (usually outside the current function, but in this case, outside the current file). I have seen nothing in K&R that says that this variable can be redeclared inside the current program unit. In other words, if the compiler writer wants to be nice, he will let you redeclare it, but he/she does not have to. (Any further comments??) Personally, I would like to be able to do this myself on occasion. For instance I would like to put the "extern" declaration in an include file which is included in several source files, and then "redeclare" it in one of them. Also, I'd like to have the compiler then make sure that the two declarations are compatible (so I don't declare "thing" as a long int in the include file, and as a char in the code.) But what we really needed from K&R is a method of declaring variables outside of functions in include files so that these variables only need to be declared once. For instance, if file a.h has the declaration "int thing;", and a.h is included by b.c and c.c, does b.c access the same "thing" that c.c does? I don't think that K&R specify. And if the declaration is "extern int thing" then there must still be a further declaration of "thing" somewhere else. (Anybody got anything else to say???) Sorry it got so long. There's more than one way to be savage, Lowell Savage
mikeb@inset.UUCP (Mike Banahan) (10/08/85)
The orginal article asked what should happen in this sort of case: /***********************************/ extern int xxx; f(){ xxx = 1; } static int xxx; /* `extra' information about xxx */ /***********************************/ The ANSI committee had a lot of work to do on this one. There is an even worse issue than that: /***********************************/ f(){ { extern int xxx; /* OH BOY!!! - where am I visible? */ /* Am I really extern? */ } } y(){ /* can I use xxx in here ???? */ } /***********************************/ They had to come up with a lot of words to fix that stuff - basically, it just wan't written down anywhere what was supposed to happen. Bill Plauger described the whole mess as ``Driving a coach and horses through block structure.'' The more I look at it, the more I agree. X3J11 has come up with a set of answers on what should happen. Because nobody really ``knew'' before, you just get what your compiler happens to give you. Be warned - it is *highly* nonportable practice, because different compilers currently do different things. This is one area where the language was already broken. The standard has chosen one way of patching it. -- Mike Banahan, Technical Director, The Instruction Set Ltd. mcvax!ukc!inset!mikeb
twb@hoqam.UUCP (BEATTIE) (10/09/85)
> > From the way I read K&R, the "static" keyword is redundant, unless > it is inside a function. In other words, "static int thing;" is > equivalent to "int thing;" unless the declaration takes place inside > a function. (Any comment on that??) > In K&R, page 80: "An external static variable is known within the remainder of the source file in which it is declared, but not in any other file" "Regular" external variables can be declared in one file and referenced in another thru the "extern" statement. Tom. ~!{ihnp4|hou2g|allegra|mhuxh}!hoqam!twb Snacktrek - n. The peculiar habit, when searching for a snack, of constantly returning to the refrigerator in hopes that something new will have materialized.
guy@sun.uucp (Guy Harris) (10/10/85)
> From the way I read K&R, the "static" keyword is redundant, unless > it is inside a function. In other words, "static int thing;" is > equivalent to "int thing;" unless the declaration takes place inside > a function. (Any comment on that??) Yup. How about "wrong"? 11.2 "Scope of externals": Identifiers declared "static" at the top level in external definitions are not visible in other files. And identifiers not so declared *are* visible in other files... Guy Harris
devine@asgb.UUCP (Robert J. Devine) (10/10/85)
> From the way I read K&R, the "static" keyword is redundant, unless > it is inside a function. In other words, "static int thing;" is > equivalent to "int thing;" unless the declaration takes place inside > a function. (Any comment on that??) It is not equivalent. Declaring a variable as "static int abc;" means that "abc" is not exported to the linker. "int def;" is exported and hence can be referenced in other files. The default storage class is "extern". > Then, the "extern" keyword specifies that the variable declared is > contained in some other program unit (usually outside the current > function, but in this case, outside the current file). I have seen > nothing in K&R that says that this variable can be redeclared inside > the current program unit. In other words, if the compiler writer > wants to be nice, he will let you redeclare it, but he/she does > not have to. (Any further comments??) To be pedantic, there are two types declarations that are possible for external variables -- one that defines and one that references. As an example, what does "extern int abc;" mean in a file? That is, is it referencing a definition of "int abc" from a different file? Or is this where abc is defined? Difference compilers do different things in this case. A portable (?) way of declaring variables that are used in different files is to have one declaration be the definition. To do this, initialize it and don't use "extern" in its declaration. Bob
peter@graffiti.UUCP (Peter da Silva) (10/12/85)
Answer: no. At least not according to the available Ritchie documentation. > The orginal article asked what should happen in this sort of case: > > /***********************************/ > extern int xxx; > > f(){ > xxx = 1; > } > > static int xxx; /* `extra' information about xxx */ > /***********************************/ > > The ANSI committee had a lot of work to do on this one. Why? It's perfectly obvious. The scope of a "global scope" declaration is the entire file after the declaration. It is not known before the declaration. If the extern keyword is used, storage is assumed to be allocated elsewhere. If the static keyword is used, the name is local to the file (useful when building libraries). The above code is not correct 'C', since xxxx is redeclared. > There is an even worse issue than that: > > /***********************************/ > f(){ > { > extern int xxx; /* OH BOY!!! - where am I visible? */ > /* Am I really extern? */ > } > } > > y(){ > /* can I use xxx in here ???? */ > } > /***********************************/ No. The scope of a declaration within a block is the remainder of the block. xxx is known within the block, nowhere else. I don't know about Plauger, but this is all explained in various ancillary documents to the UNIX programmer's manual.
oleg@birtch.UUCP (Oleg Kiselev x268) (10/16/85)
> From the way I read K&R, the "static" keyword is redundant, unless > it is inside a function. In other words, "static int thing;" is > equivalent to "int thing;" unless the declaration takes place inside > a function. (Any comment on that??) > Yes! "static" means that only the file where the "static <whatever> thing" is declared will know about it! It's usefull for doing data hiding and modular a la Ada developement ( Thanks to Dan Berry for teaching how to do it right!) > For instance, if file a.h has the > declaration "int thing;", and a.h is included by b.c and c.c, does > b.c access the same "thing" that c.c does? I don't think that K&R > specify. And if the declaration is "extern int thing" then there must > still be a further declaration of "thing" somewhere else. (Anybody > got anything else to say???) As a matter of fact! Yes they do. The linker takes care of resolving this type of reference. If you have ever written a linker you'd know! As long as we are at it : if a.h declares "static <whatever> thing" and is included by b.c and c.c, b.c and c.c see different things. And if b.c declares "static <> thing;" and c.c "extern <> thing" linker will complain about undefined "_c" in c.c! Also, if you have "extern <> thing" and "static <> thing" static declaration supercedes the external and is the one seen in the file. And equivalent "extern" and "auto" declarations are mapped into the same location. And, yes, declaring the same variable two different types is a no-no in the same file. > Lowell Savage -- -----------------------------------+ With deep indifference, "I disbelieve an army of invisible | Oleg Kiselev. mind-flayers!" | DISCLAIMER: "OK. They are *still* not there." | I don't know what I am talking about and -----------------------------------+ therefore am not responsible for any damages to people who take me seriously! ...!trwrb!felix!birtch!oleg ...!{ihnp4|randvax}!ucla-cs!uclapic!oac6!oleg Nothing I ever say reflects the views or opinions of my employers. They knew who they hired though!
gwyn@BRL.ARPA (VLD/VMB) (10/19/85)
There are several interrelated aspects of "static" and "extern" due to overloading these keywords. X3J11 has made a very good stab at spelling out all the relevant aspects. Look it up.