[comp.lang.c++] extern - when to use it

kearns@read.columbia.edu (Steve Kearns) (07/29/89)

Would someone post an article explaining the proper use of
extern when declaring function?  When is it neccessary, 
just a good idea, a bad idea?  What about the new
'extern "C" ' I have been hearing about?

-steve

ark@alice.UUCP (Andrew Koenig) (07/29/89)

In article <6420@columbia.edu>, kearns@read.columbia.edu (Steve Kearns) writes:

> Would someone post an article explaining the proper use of
> extern when declaring function?  When is it neccessary, 
> just a good idea, a bad idea?  What about the new
> 'extern "C" ' I have been hearing about?

Saying `extern' by itself in a function declaration has no effect.
Thus

	extern void munge();

means precisely the same thing as

	void munge();

extern "C" is new in C++ 2.0 .  You must use it to declare any C function
you wish to call from C++ or any C++ function you wish to call from C:

	extern "C" double sqrt(double);

The declaration informs the C++ compiler that sqrt(double) is
a C function so that it can use a C calling sequence for it
(which is therefore no longer required to the be the same as
the C++ calling sequence).  Similarly:

	extern "C" void frob() {
		// stuff
	}

says that frob() is a function that will be called from C.
-- 
				--Andrew Koenig
				  ark@europa.att.com

dld@F.GP.CS.CMU.EDU (David Detlefs) (07/31/89)

I discovered recently in using G++ that Tiemann has implemented
'extern "C"' so that structure declarations occuring with them do not
become part of the namespace in the same way that they do in C++
linkage.  That is, if you write

extern "C" { struct foo { int i; } }

then later in the code "foo" is not recognized as a type name --
instead you must (as in C) use "struct foo".  At first I thought this
was a bug, because I had seen no mention of this behavior, but when it
was explained to me that this is a feature, it began to seem like a
great idea.  It solves a number of problems, the chief of which is
when a standard C header file declares a structure and a function with
the same name.  Cases I've found in our BSD4.3-type system include
"timezone" and "wait".

So, is this part of C++ 2.0?  I could not find any reference to this
feature in either Lippman's C++ Primer or Stroustrup's "Type-safe
Linkage" paper.  Are there any drawbacks to this that I (and Michael
Tiemann, I guess) don't see?  If not, is there any chance it will
become part of the language specification?
--
Dave Detlefs			Any correlation between my employer's opinion
Carnegie-Mellon CS		and my own is statistical rather than causal,
dld@cs.cmu.edu			except in those cases where I have helped to
				form my employer's opinion.  (Null disclaimer.)

bs@alice.UUCP (Bjarne Stroustrup) (08/02/89)

It has been suggested that changing the semantics of structure tags
declared under `extern "C"' would be a good idea. For example,

	extern "C" { struct S { ... }; }

would not put `S' in the ordinary name space.

I think this is an ugly and unnecessary `compatibility' hack.

(1) This extension is unnecessary because the resolution of names in 2.0
reduces the incompatibilities to the perverse case:

	struct S { ... };
	typedef int S;	/* legal C, illegal C++ */
	S a;		/* an int */
	struct S b;	/* an S */

and to scope effects:

	int S;
	f() {
		struct S { ... };
		int i = sizeof(S);	/* C and C++ differs! */
	}

In particular, 2.0 gets the following examples right:

	struct stat { /* ... */ };
	
	extern "C" int stat(const char*, struct stat*);

	g() {
		struct stat a;
		int i = stat("asdf",&a);
	}


	struct proc { /* ... */ int i; } proc;

	h()
	{
		struct proc a;
		proc.i = 1;
		a.i = 1;
	}

(2) This extension has the probable undesirable effect of making the `struct S'
notation common in C++. The requirement to prefix all structure tags with the
keyword `struct' was an early compatibility hack in C and I have no wish to see
regress to the point where C++ programs are decorated with redundant `struct'
`enum' 'union' and `class' qualifiers. The observation is that almost all C-style
uses of identifiers to name both an object and a type name occur in minimally
transcribed C programs and interfaces to C programs. The suggested extension
would encourage people to use `extern "C"' for all structs that could possibly
be used from C programs. The - often unintentional - undesirable side effect
would be to deny the C++ notational convenience. 

(3) When used for functions `extern "C"' has no effect on the type checking of
the program (except for checking that there is not two functions of the same name
with C linkage - since there cannot be). The suggested extension thus is a major
departure that could set a precedense that most likely would lead to of all kinds
of permutations of semantics based on `extern "C"' `extern "Pascal"' etc. to suit
individual implementations and damage portability of programs relying on such
local extensions. In other words, `extern "C"' was designed to govern the relation
between a C++ program and its environment. The proposed extension uses it to
govern the internal operation of a C++ program.

(4) This extension takes up a syntactic construct and could thus prevent future
alternative interpretations. I have no such plans, but one plausible interpretation
of `extern "C"' for structure definitions would be to enforce a particular
`compatible' layout strategy for such structs in a C++ implementation that would
optimize the layout of C++ structs along different lines from a C implementation.
It seems rash to use up this notation except for major gain.

None of these arguments against the extension are compelling but taken together
I see them as sufficient to reject the extension because they show it as not
obviously needed and not obviously harmless.

Note that there are hundreds of little ways in which C++ could be improved.
Unless great restraint is excersized, C++ will crumble under the burden and
complexity of all those `nice' features - and here I'm only talking about
the sensible and useful extensions.