[comp.std.c] extern int f

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.