[comp.lang.c] storage class != Storage Class

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

>In article <7374@utzoo.UUCP>, henry@utzoo.UUCP writes:
>> Can you name a few?  Extern is the way it has always been in C; compilers
>> which default to static are broken.  (Please don't cite C++, that isn't C.)
>> -- 
In article <6430@alice.uUCp> bs@alice.UUCP writes:
>
>Most (all?) C compilers and lint will accept the following program:
>
>file1:
>
>	typedef int I;
>	I i = 1;
>
>file2:
>	typedef char* I;
>	I p = "asdf";
>
>Is it legal? Personally, I think not because the name I which is external by
>default has two definitions (but the C++ compiler also accepts it).
>
But the storage class is given: 'typedef'. See pg 200, 8.8. In C, there
are really only three 'Storage Classes' per se: static, auto, and
register (the heap is supported entirely by run-time code).  Auto is on
the stack and static is at a constant address. All functions are static
in this sense.

However, storage class specifiers are used to specify more than just
Storage Class.  The concept of 'extern' has nothing to do with where an
object is stored, but rather refers to the scope of its name during linking.
'typedef' names such as 'I' above are not objects and do not exist
after compilation. So it makes no sense to apply a Storage Class of any
form to 'I'. You are suggesting that the 'link-time scope' rules should
be extended to typedefs (if only to make the example illegal), but
neither of these concepts apply to 'Storage Class'. They are two
different things which sc-specifiers have been made to do in addition
to specifying Storage Class.

It is worth noting at this point that the default storage class
(!=Storage Class) for top-level data definitions is neither static nor
exactly extern:

static	int	a;
	int	b;	/* all three mean different things */
extern	int	c;
--------------- cc -S ---------
	.lcomm	_a,4
	.comm	_b,4

The definition of 'b' produces a common-block definition while 'c' does
not. Under this implementation of C, you can write 'int b' in more than
one file, but under many others, you can write 'int a' in only one
file, and all others must say 'extern int b'.

So there are three 'storage classes' (really link-time scope classes)
for top-level objects:

(1) static: object is defined here in this file and is not externally visible.
(2) <none>: object is defined here in this file and *is* externally visible.
(3) extern: object is not defined here but is available externally.

...with a few exceptions for convenience:
char *getenv();
is treated as 'extern char *getenv()' since it is obviously not defined
there.  A definition of type (3) can exist in the same file with a (2)
and then the type (3) definitions have no effect, other than allowing
forward definition of type.
Again, all top-level objects have static Storage Class.

..and of course...
(4) typedef: not an object but a type, obviously not visible externally.
-- 
----------------------------------------------------------------------
Greg Smith     University of Toronto      UUCP: ..utzoo!utcsri!greg
Have vAX, will hack...

karl@haddock.UUCP (12/13/86)

In article <3745@utcsri.UUCP> greg@utcsri.UUCP (Gregory Smith) writes:
>So there are three 'storage classes' (really link-time scope classes)
>for top-level objects:
>
>(1) static: object is defined here in this file and is not externally visible.
>(2) <none>: object is defined here in this file and *is* externally visible.
>(3) extern: object is not defined here but is available externally.

Which brings up an interesting question:  How do you declare an object which
is not being defined at this point and is not available externally?  Is there
a portable way to make a forward declaration of a static variable?  (I've been
using "extern", but I wonder if that really works on all compilers.)

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

henry@utzoo.UUCP (Henry Spencer) (12/16/86)

> ...  How do you declare an object which
> is not being defined at this point and is not available externally?  Is there
> a portable way to make a forward declaration of a static variable?  (I've been
> using "extern", but I wonder if that really works on all compilers.)

Alas, it's not X3J11-compliant.  The current X3J11 drafts (well, the most
current that I've seen -- I haven't got the official public-comment one
yet) say that the first appearance of the name makes the rule, so you must
say "static" on its first appearance.  Unfortunately, a lot of existing
compilers don't like this.  (For that matter, *I* don't like it, but I am
not optimistic about getting it changed.)  My current custom is to declare
variables like that with "STATIC int foo;" and then feed the compiler
something suitable with a -DSTATIC=whatever.
-- 
				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,decvax,pyramid}!utzoo!henry