[comp.lang.c] extern question

faustus@ic.Berkeley.EDU (Wayne A. Christopher) (07/01/88)

Is the following acceptable C code:

	extern int foo();

	bar()
	{
		int (*bla)() = foo;	/* CASE 1 */

		foo();			/* CASE 2 */
	}

	static int
	foo()
	{
		...
	}

In other words, should extern be interpreted as "possible forward
reference" (the way I'm using it), or "externally defined symbol"?  All
the compilers I have used handle case 2 ok, but one couldn't deal with
case 1.  Shouldn't they both work the same?

From an aesthetic viewpoint, I like to use extern anywhere I declare
something but don't define it.  I think writing

	int foo();

for static functions is not as clear.

	Wayne

gwyn@brl-smoke.ARPA (Doug Gwyn ) (07/02/88)

In article <4182@pasteur.Berkeley.Edu> faustus@ic.Berkeley.EDU (Wayne A. Christopher) writes:
>Is the following acceptable C code:

No.

>From an aesthetic viewpoint, I like to use extern anywhere I declare
>something but don't define it.  I think writing
>	int foo();
>for static functions is not as clear.

What you should have written was

	static int foo();

Aesthetics and proper use of the language have no necessary connection.

leo@philmds.UUCP (Leo de Wit) (07/02/88)

In article <4182@pasteur.Berkeley.Edu> faustus@ic.Berkeley.EDU (Wayne A. Christopher) writes:
|Is the following acceptable C code:
|
|	extern int foo();
|
|	bar()
|	{
|		int (*bla)() = foo;	/* CASE 1 */
|
|		foo();			/* CASE 2 */
|	}
|
|	static int
|	foo()
|	{
|		...
|	}
|
|In other words, should extern be interpreted as "possible forward
|reference" (the way I'm using it), or "externally defined symbol"?  All
|the compilers I have used handle case 2 ok, but one couldn't deal with
|case 1.  Shouldn't they both work the same?
|
|From an aesthetic viewpoint, I like to use extern anywhere I declare
|something but don't define it.  I think writing
|
|	int foo();
|
|for static functions is not as clear.
|
|	Wayne

Indeed. You should write

static int foo();

This is - in my point of view - the only correct forward declaration.
It is also better from aesthetic point of view, in that it does use the
correct storage type. Notably the Lattice C compiler is rather strict
regarding storage classes / extern definitions; I like that. As for
extern declarations, they typically belong in a header file (the one
that belongs to the module defining the extern function / variable, i.e.
is the - outgoing - interface of that module to the outside world).

      Leo  (that's the way I C it; don't blame me for being stubborn 8-).

karzes@mfci.UUCP (Tom Karzes) (07/04/88)

In article <8200@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>What you should have written was
>
>	static int foo();
>
>Aesthetics and proper use of the language have no necessary connection.

I've always found K&R to be very obscure on external declarations.  Among
other things, they don't explicitly say that static can be used for forward
function declarations, although pcc-based C compilers have always allowed
it, and it makes sense.

However, I still consider static forwards to be broken in C.  Sure, they
work for functions, but what about data?  For example, consider the
following:

        struct foo {
            int         a;
            struct bar *bar_ptr;
        };

        struct bar {
            int         b;
            struct foo *foo_ptr;
        };

        extern struct foo   x;
        extern struct bar   y;

        struct foo  x = {123, &y};
        struct bar  y = {456, &x};


Now suppose you want to make x and y static.  What do you do?  You still
need a forward declaration for at least one of them in order to refer to
it in an initialization list.  Unless there's some way to do this that I
don't know about, it's a glaring hole in C.  Even if this case didn't
matter, it would still be nice to be able to issue forward declarations
for static data.  Does anyone know if this has been fixed in ANSI C
(e.g., by allowing something suitably gross like "extern static" as a
forward declaration)?

gwyn@brl-smoke.ARPA (Doug Gwyn ) (07/05/88)

In article <457@m3.mfci.UUCP> karzes@mfci.UUCP (Tom Karzes) writes:
>        extern struct foo   x;
>        extern struct bar   y;
>        struct foo  x = {123, &y};
>        struct bar  y = {456, &x};
>Now suppose you want to make x and y static.  What do you do?  

Same thing, but include "static" in all declarations that mention
them, particularly the first.

	static struct foo x;
	static struct bar y;
	static struct foo x = { 123, &y };
	static struct bar y = { 456, &x };

karzes@mfci.UUCP (Tom Karzes) (07/06/88)

In article <8213@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
}Same thing, but include "static" in all declarations that mention
}them, particularly the first.
}
}	static struct foo x;
}	static struct bar y;
}	static struct foo x = { 123, &y };
}	static struct bar y = { 456, &x };

That might work in ANSI C, but it isn't legal K&R C.  In K&R C the second
declarations of x and y constitute illegal redeclarartions, and with the
compilers I've tried compilation fails with a user error.