brad@SSD.CSD.HARRIS.COM (Brad Appleton) (02/10/90)
Are the following function declarations equivalent? (1) extern int foo(); (2) int foo(); I was just asked this question and I thought I knew a precise answer but I find that I am a little fuzzy on this one! I thought (2) is like a "forward" declaration in Pascal and that the only difference between these two is that If I use (2) then I may define the function "foo" (give it a body) later on in the same file. Is this right? I have looked in K&R (2e) and Harbison-Steele to try to find the answer (as well as a few other texts) but nothing I have read seems to state the difference between these two in precise terms (IMHO at least)! When would I use (1) and not (2) (and vice-versa)? Is this dependent on the Compiler Vendor? Is the answer different between ANSI-C and non-ANSI C? I am somewhat new to the net and would also appreciate some constructive feedback on whether this issue is worthy/appropriate for this newsgroup! (any responses that are strictly feedback and not an answer to my question stated in the subject line should probably reply by e-mail). TIA (Thanks in Advance). -- Brad Appleton "... and miles to go before I sleep." +-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+ | Harris Corporation | brad@csd.harris.com | | Computer Systems Division, M/S 161 | {uunet,novavax}!hcx2!brad | | 2101 West Cypress Creek Road | | | Fort Lauderdale, FL 33309 USA | Phone: (305) 973-5007 | +-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+ Brad Appleton "... and miles to go before I sleep." +-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+ | Harris Corporation | brad@csd.harris.com | | Computer Systems Division, M/S 161 | {uunet,novavax}!hcx2!brad | | 2101 West Cypress Creek Road | | | Fort Lauderdale, FL 33309 USA | Phone: (305) 973-5007 | +-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+
gwyn@smoke.BRL.MIL (Doug Gwyn) (02/11/90)
In article <2912@hcx1.SSD.CSD.HARRIS.COM> brad@SSD.CSD.HARRIS.COM (Brad Appleton) writes: >Are the following function declarations equivalent? >(1) extern int foo(); >(2) int foo(); >When would I use (1) and not (2) (and vice-versa)? >Is this dependent on the Compiler Vendor? >Is the answer different between ANSI-C and non-ANSI C? This is a messy issue, because existing implementations differed in this. The Standard situation for functions is simpler than for objects; the latter involves the notion of "tentative definition" as well as linkage. I'm just going to explain linkage here. First, be sure you know the difference between object (data) and function. Next, recall that there are four scopes of identifier visibility: function-scope (labels only) function-prototype scope (parameters in declarations only) file-scope (declared outside blocks) block-scope (declared inside a block, also parameters in definitions) Inner declarations can hide outer ones until the inner scope terminates. Finally, linkage is determined as follows: if not object and not function or function parameter or block-scope and object and not specified "extern" then no linkage; done fi if function and no storage-class-specifier then set storage-class-specifier to "extern"; proceed fi if specified "extern" { object or function } then if there was a visible file-scope declaration then linkage is same as visible file-scope's; done else linkage is external; done fi fi if file-scope then case storage-class-specifier in "static": linkage is internal; done none: { object } linkage is external; done esac fi If the same identifier has both internal and external linkage within the same translation unit (source module including headers), the behavior is undefined. If an identifier has no linkage, it is denotes a unique entity. All instances of the same identifier with internal linkage in the same translation unit denote the same object or function. All instances of the same identifier with external linkage in the entire program denote the same object or function. Fortunately there is a simple set of rules the programmer can use to avoid the "grey areas" of the linkage rules: Always declare objects and functions that will be defined by some other translation unit or library with explicit "extern". Always define objects and functions that are published for other translation units to use without a storage-class-specifier. Always define functions and file-scope objects that are NOT intended for use by other translation units with explicit "static". If you're using a header file to define externally-visible interfaces (a recommended practice), always use "extern" in its object and function declarations (but not in type definitions). >I am somewhat new to the net and would also appreciate some constructive >feedback on whether this issue is worthy/appropriate for this newsgroup! It's a legitimate question.
khera@juliet.cs.duke.edu (Vick Khera) (02/12/90)
In article <2912@hcx1.SSD.CSD.HARRIS.COM> brad@SSD.CSD.HARRIS.COM (Brad Appleton) writes: > >Are the following function declarations equivalent? > >(1) extern int foo(); >(2) int foo(); > >Brad Appleton "... and miles to go before I sleep." Under Microsoft C 5.1, the two declarations were just slightly different. If I put "extern int foo(/* some prototype */);" in my header files, then when I compiled the file containing foo() [which #included the header file], I would not get any error messages if the parameter list or function types mismatched. If the header file contained "int foo(/* some prototype */);" then the I would get the proper messages. In both cases, other files (not containing the definition of foo() ) would compile the same, generating the appropriate messages. A friend of mine tells me that he worked with a compiler recently that would complain about a function having a duplicate declaration if the extern form was not used when the file containing the definition was compiled. v. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Vick Khera Department of Computer Science ARPA: khera@cs.duke.edu Duke University UUCP: ..!{mcnc,decvax}!duke!khera Durham, NC 27706
karl@haddock.ima.isc.com (Karl Heuer) (02/13/90)
Doug already posted the details, but it might not be clear what the answer is to the original question. In article <2912@hcx1.SSD.CSD.HARRIS.COM> brad@SSD.CSD.HARRIS.COM (Brad Appleton) writes: >Are the following function declarations equivalent? >(1) extern int foo(); >(2) int foo(); Yes. They are completely identical in any sane compiler. >I was just asked this question and I thought I knew a precise answer but >I find that I am a little fuzzy on this one! I thought (2) is like a >"forward" declaration in Pascal and that the only difference between these >two is that If I use (2) then I may define the function "foo" (give it >a body) later on in the same file. Is this right? With either spelling, the actual definition for the function can appear in either the same file or in a different file. (Some people prefer to use "extern" for functions defined in separate files and omit "extern" for forward declarations; this is a matter of taste.) But it must be a global function. To forward-declare a static function%, you should use "static int foo();". When dealing with objects rather than functions, the situation gets worse. Karl W. Z. Heuer (karl@ima.ima.isc.com or harvard!ima!karl), The Walking Lint ________ % There may be some compilers that won't let you forward-declare a static function. If you have to deal with such a beast, it's probably best to sort the function definitions (if they aren't mutually recursive) or promote one of them from static to global so you can forward-declare it.