[comp.lang.c] forward declaration of array; how?

ok@cs.mu.oz.au (Richard O'Keefe) (10/10/89)

I have a program which uses a statically initialised array of function
pointers (a couple of hundred of them).  At the moment, the file which
contains the array looks like
	...
	extern void (*(dispatch[]))();
	...
	void foo() { ... (*dispatch[i])(); ... }
	...
	void baz() { ... (*dispatch[j])(); ... }
	...
	static void (*(dispatch[]))() = { ... foo, ..., baz, ... };
	...
I want to make the program ANSI-conformation.  GCC prints a warning about
this; it doesn't like dispatch[] being extern and static both.  Neither
do I, but it was the only way I could talk another C compiler into accepting
it.  How should I organise this in ANSI C?  I'd really rather _not_ add
a couple of hundred function prototypes.

karl@haddock.ima.isc.com (Karl Heuer) (10/12/89)

In article <2364@munnari.oz.au> ok@cs.mu.oz.au (Richard O'Keefe) writes:
>	extern void (*(dispatch[]))();
>	static void (*(dispatch[]))() = { ... foo, ..., baz, ... };

The ANSI way to do this is to use `static' rather than `extern' in the first
declaration.  This makes it a `tentative definition', which can be thought of
as a kludge around the ambiguity between declarations and uninitialized
definitions; it retroactively becomes a definition only if no real definition
appears before the end of the translation unit.  In this case, the initialized
declaration later on would be the real definition, causing the earlier one to
be treated as a forward declaration only.

Unfortunately, not all existing pre-ANSI compilers agree with this.  Even more
unfortunately, some do not have *any* way to forward-declare a static object,
so you can't just use `#if __STDC__ static #else extern #endif' and expect it
to be portable.  For full portability (without rearranging it to be a backward
reference), you'd need to make the `dispatch' object global instead of static.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

ok@cs.mu.oz.au (Richard O'Keefe) (10/12/89)

In article <2364@munnari.oz.au> ok@cs.mu.oz.au (Richard O'Keefe) writes:
>	extern void (*(dispatch[]))();
>	static void (*(dispatch[]))() = { ... foo, ..., baz, ... };
In article <14868@haddock.ima.isc.com>, karl@haddock.ima.isc.com (Karl Heuer) writes:

: The ANSI way to do this is to use `static' rather than `extern' in the first
: declaration.

I received E-mail from two other people suggesting this.
It's obvious enough, in all conscience, to make the two declarations
agree about the storage class.  The trouble is that the nearest thing
to an ANSI compiler available to me is gcc 1.36, which doesn't like it.
As the man says:

: Unfortunately, not all existing pre-ANSI compilers agree with this.

Oh well, I should have known I was asking for trouble when I had to use
the extern/static hack to make the PDP-11 compiler happy way back when.