Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/18/84; site utcsri.UUCP Path: utzoo!utcsri!greg From: greg@utcsri.UUCP (Gregory Smith) Newsgroups: net.lang.c Subject: Re: Proper use of "extern" ... Message-ID: <2964@utcsri.UUCP> Date: Thu, 12-Jun-86 13:57:20 EDT Article-I.D.: utcsri.2964 Posted: Thu Jun 12 13:57:20 1986 Date-Received: Thu, 12-Jun-86 14:23:16 EDT References: <223@comp.lancs.ac.uk> <132@danews.UUCP> Reply-To: greg@utcsri.UUCP (Gregory Smith) Organization: CSRI, University of Toronto Lines: 85 Summary: In article <132@danews.UUCP> lvc@danews.UUCP (Larry Cipriani) writes: >My understanding of extern is that it simply declares the >object in question. That is, the compiler is told what >type the object is. I don't know of any other use for extern. > >> f uses g and g is declared after f (I know we can put g before >> f and the following is no longer applicable but ...). >> >> At the top of this file do we put >> a) static void g() or >> b) extern void g()? (extern static must be meaningless). Yes, extern static is a systax error. only one storage class may be specified. >> My understanding (this varies with the book you read) of "extern" is that >> it means the object is declared "later in this file or in another file" in >> which case I vote for (b). Is this right? > >Yes, but for the wrong reason. > I don't think the reason is wrong. Choice (b) is wrong: It not only declares the type of v but asserts it as static. consider this: static foo(),blat(); extern bar(),xxx(); static blat(){} bar(){} foo(){} /* "foo.c", line 6: redeclaration of foo */ On line 6 I try to pass off foo as a non-static ( externally visible ) function when I have already declared it to be static. Everything else works ok. 'nm foo.o', after deleting last declaration, includes this: 00000008 T _bar ; bar defined inside and usable externally. 00000000 t _blat ; blat defined inside, but not externally defined. xxx is not included. I guess what Larry is saying is " extern xxx(); obviously does not declare xxx to be in another file" which is a good point - there need exist no xxx for the above to work. However I don't think the distinction is a reliable one: >I often put ALL of the declarations in one header file, and include >it in all the other files. This is a matter of style, and I recognize >its weaknesses, but I like it better than all the alternatives. By the >way, extra, redundant, or unnecessary externs are allowed and don't matter, >at least on my C compiler. >-- what about extra, redundant, or unnecessary adjectives? :-) no offense, I just couldn't resist that :-). Actually, I think this is mostly a result of the behaviour of the UNIX assemblers. All undefined symbols are assumed by the assembler to be defined externally. So the compiler does not include any declarations for these in its output. As a result, 'xxx' will not appear in the assembler file at all. Some assemblers require external references to be declared as such, and thus the compiler might emit '.extern xxx' even though xxx is never used. That would then cause the linker to try to load xxx. I don't know whether such behaviour is considered 'standard C' or not. The whole area of C external definitions is a bit of a mess. A main problem is that the default storage class depends on the type of the identifier, and can be different from any explicit storage class. I.e. the following are all different: int x; static int x; extern int x; These are equivalent: char *foo(); extern char *foo(); Also, 'storage class' is a misnomer, since all external objects live in static storage. And what about typedef? On the other hand, I feel that K&R does explain all this weirdness very well. That may be because I was already familiar with linking loaders before using C. -- "Shades of scorpions! Daedalus has vanished ..... Great Zeus, my ring!" ---------------------------------------------------------------------- Greg Smith University of Toronto UUCP: ..utzoo!utcsri!greg