[net.lang.c] Proper use of "extern" ...

david@comp.lancs.ac.uk (David Coffield) (06/05/86)

Right.
Suggestions, please, as to the correct use of "extern" in the
following scenario:

A file has two functions in it, "f" and "g", thus

	static void f()
	{
		g();
	}

	static void g()
	{
	}

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).

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?
-- 
"the secret of success is compost"

uucp:   ...!mcvax!ukc!dcl-cs!david     post: Department of Computing
arpa:   david%lancs.comp@ucl.cs              University of Lancaster, UK
janet:  david@uk.ac.lancs.comp	       phone: +44 524 65201 x 4599

keppel@pavepaws.berkeley.edu (David Keppel) (06/08/86)

In article <223@comp.lancs.ac.uk> david@comp.lancs.ac.uk (David Coffield) writes:
[ forward declaration of a static function: use static or extern keyword? ]
>
>At the top of this file do we put
>a) static void g() 	or
>b) extern void g()?	(extern static must be meaningless).
>
>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?

	Since static means (more or less) 'local', I'd vote for 'static',
    since it tells you right away that the declaration is somewhere *in
    this file*, whereas 'extern' tells you to *look elsewhere*.

	How does this match with 'standard practice'?
----
    :-D avid  K eppel				    ..!ucbvax!pavepaws!keppel
		"Learning by Osmosis: Gospel in, Gospel out"

alastair@axis.UUCP (Alastair Adamson) (06/09/86)

[feed this line to the Orcs]
In article <223@comp.lancs.ac.uk> david@comp.lancs.ac.uk (David Coffield) writes:
>Suggestions, please, as to the correct use of "extern" ..
>At the top of this file do we put
>a) static void g() 	or
>b) extern void g()?	(extern static must be meaningless).

I would always prefer a) since it helps the reader by making explicit
the fact that the function is local to this file. Further, I like to
declare all extern (other file, library) functions and static functions
before the definition of the first function in a file, after any #includes,
#defines and global variables, as in:

	#include	lines
	#define		lines
	global variables (definitions)
	extern globals   (declarations)
	static functions (declarations)
	extern functions (declarations)
	function definitions

Thus, I would also have said "static void f()" before f()'s definition.

There is a problem with static functions, namely that some C compilers
don't know how to handle them and generate illegal instructions so
that the assembler stage bombs out. You may say that one should avoid
such ridiculous compilers and I would agree with you. Unfortunately,
however, when porting software to other computers one has to put up
with what's available!

lvc@danews.UUCP (Larry Cipriani) (06/09/86)

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.

When you define the object, you tell the compiler the
type, and allocate space for it, etc.

> A file has two functions in it, "f" and "g", thus
> 
> 	static void f()
> 	{
> 		g();
> 	}
> 
> 	static void g()
> 	{
> 	}
> 
> 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).

Again, I don't mean to be picky, but f and g are "defined" here,
not "declared".  Any book that doesn't follow this convention is wrong.

> 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 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.
-- 

Larry Cipriani		AT&T Network Systems
danews!lvc		"Nothing is worse than an itch you can never scratch."

davidsen@steinmetz.UUCP (Davidsen) (06/12/86)

I just tried the declaration
  static int foo();
on SysV, BSD, XENIX/286, and a couple of spare C compilers laying around. They
all loved it. Even lint accepts it. This has to qualify as current practice,
at least.

I do know of two compilers which will not let you say extern and then
change to static later in the program, so this is not universal
practice.

X3J11 talked about a program like:

static foo();

part1() {
  extern foo();

  foo(20);
}

part2() {
  foo(20);
}

static foo(n)
  int n;
{
  mumble(n+1);
}

in terms of which 'foo' is called in part1. Since declarations inside a
procedure mask global declarations, if 'foo' inside part1 another foo,
which is extern?

I left X3J11 after 2 years and I can't find anthing in the latest
version of the standard I have (I keep getting the March 85 version
from CBEMA) which would clarify the issue.
-- 
	-bill davidsen

  ihnp4!seismo!rochester!steinmetz!--\
                                       \
                    unirot ------------->---> crdos1!davidsen
                                       /
         sixhub ---------------------/        (davidsen@ge-crd.ARPA)

"Stupidity, like virtue, is its own reward"

greg@utcsri.UUCP (Gregory Smith) (06/12/86)

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

brett@wjvax.UUCP (06/13/86)

In article <132@danews.UUCP> lvc@danews.UUCP (Larry Cipriani) writes:
>My understanding of extern is that it simply declares the
>object in question...
>
>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.

Harbison & Steele say only that this property is true of the 4.2bsd C
compiler.  Speaking of its treatment of extern, they say:

	"If the identifier so declared is never actually used, the compiler
	will not issue an external reference to the linker" (H & S, p. 82)

I find this feature very useful, since I often generate a library which one
associated include file that contains external references to all the routines
therein.  This frees the user of my library from having to declare all the
routines himself (at least those that don't return in).  This is a minor
advantage.  A MAJOR advantage is that it also lets me transparently convert
some routines to macros, or back again.  If the user had declared them, I
could not convert a routine to a macro without REMOVING all the user's
declarations.

However, if the above feature is not present, each external reference in the
include file causes the subroutine to be linked in, with the result that anybody
that uses my include file and my library gets the ENTIRE library linked in,
no matter how many routines he actually used.  This would be annoying.

My question is -- how general is this feature?  Is it true of AT&T SYSV?  Is it
true of some of the common PC C compilers?  Other C compilers?

-------------
Brett Galloway
{pesnta,twg,ios,qubix,turtlevax,tymix,vecpyr,certes,isi}!wjvax!brett

gwyn@brl-smoke.ARPA (Doug Gwyn ) (06/15/86)

In article <223@comp.lancs.ac.uk> david@comp.lancs.ac.uk (David Coffield) writes:
-	static void f()
-	{
-		g();
-	}
-
-	static void g()
-	{
-	}
-
-At the top of this file do we put
-
-a) static void g() 	or
-
-b) extern void g()?

I would put

	static void g();

The rationale is that "extern" would imply that the name "g"
is to be "published", so that it would be visible outside
this file module.  Since this is not what is wanted, "extern"
is inappropriate.

Note that existing compilers do not all agree on the scope
or meaning of extern declarations in cases like this.  The
X3J11 standard is expected to clarify these semantics.

chris@umcp-cs.UUCP (Chris Torek) (06/16/86)

>In article <132@danews.UUCP> lvc@danews.UUCP (Larry Cipriani) writes:
>>... extra, redundant, or unnecessary externs are allowed and don't
>>matter, at least on my C compiler.

In article <714@wjvax.wjvax.UUCP> brett@wjvax.UUCP (Brett Galloway) writes:
>Harbison & Steele say only that this property is true of the 4.2bsd C
>compiler. ...
>
>	"If the identifier so declared is never actually used, the compiler
>	will not issue an external reference to the linker" (H & S, p. 82)
>
>... However, if the above feature is not present, each external
>reference in the include file causes the subroutine to be linked in,
>with the result that anybody that uses my include file and my library
>gets the ENTIRE library linked in ....
>
>... how general is this feature?  ... Is it true of ... Other
>C compilers?

I submit that any compiler that does not have this `feature' is,
if not broken, at least being rather dumb.  Consider: all a compiler
need do is note at an `extern' declaration that the variable or
function is presently unused, but semantically valid.  At the first
actual reference to the variable, the compiler can generate whatever
linker commands (if any) are required to make the variable or
function available at run-time.

In this manner, a C source file consisting entirely of `extern'
declarations:

	extern int i;
	extern double d;
	extern char *cf();

would generate no code whatsoever.

For some reason, not all compiler writers seem to have realised
this; in such cases, I grit my teeth and fiddle with the source
code, but also complain vociferously.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@mimsy.umd.edu