[comp.lang.c] `static'

chris@mimsy.UUCP (Chris Torek) (08/05/88)

In article <503@draken.nada.kth.se> pk-tle@nada.kth.se (Tommy Levitte) writes:
(text in []s his, but moved)
>There are two kinds of statics:
> - External statics [defined outside functions].
> - Internal statics [defined  inside functions].
>External statics are reachable in the whole file, but internal statics are only
>available in the function in which they are defined.

This is correct, but mixes up two separate concepts (well, perhaps
this is reasonable, since the same keyword is used for both).

>A string constant is an exception to this rule.

This, however, is false.  (You too have confused scoping and storage,
at least in this explanation.)

[text written _like_this_ represents emphasis]

Static has two meanings.  It is a _storage_class_specifier_, and it is
a (link-time) _scope_specifier_.  These should be considered separately.

First, all local variables, no matter what their storage class, are
locally (block) scoped.  The differences between the declarations of x,
y, and z below are in their storage classes, not their scopes.

	f() {
		int x;		/* auto storage (the default) */
		register int y;	/* register storage */
		static int z;	/* static storage */
		...

All of these variables are accessible in f, and in any sub-blocks within
f() (unless they are hidden by a redeclaration).  `x' and `y' come into
existence when f() is called, and disappear when f() returns; new instances
appear if f() is called recursively.  `z', however, exists independent of
f(): it has _static_storage_.  There is only one copy of z; it is always
there.  It can only be _named_ from f(), but it is there whether it can
be named or not.

While all local variables are of storage class `auto' unless otherwise
specified, global variables and functions are _always_ of storage class
`static'.  That frees the keyword for its second meaning: global
variables and functions can be of _file_scope_ or _program_scope_.
Normally, globals have program scope, but adorning a global definition
with the keyword `static' makes it instead have file scope.  Objects
with file scope cannot be named outside of the source file that
defines them; objects with global scope can be so named, by declaring
them as external in another source file.  Essentially, tagging a
function or a global variable `static' makes it hidden, so that no one
but you can find it.  (It also allows you to make two or more different
objects with the same name, whether or not you meant to do so, by using
the same name in different files.  Since each file refuses to disclose
its statics, each file gets only its own version.)

Finally, returning to string constants: these are unnamed objects, and
hence the scoping rules for names are irrelevant.  There simply is no
name to be scoped.  The objects do, however, have static storage duration:
they exist at all times.  Thus, once you have a pointer to a string
constant, you can follow that pointer at any time.  The string shall
not vanish from underfoot, unless the whole program vanishes with it.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

jbeard@quintus.uucp (Jeff Beard) (08/06/88)

% Finally, returning to string constants: these are unnamed objects, and
% hence the scoping rules for names are irrelevant.  There simply is no
% name to be scoped.  The objects do, however, have static storage duration:
% they exist at all times.  Thus, once you have a pointer to a string
% constant, you can follow that pointer at any time.  The string shall
% not vanish from underfoot, unless the whole program vanishes with it.

1) program scoped static char * foo may be altered anywhere by any procedure
   and thus the original string reference will be lost to all, even though 
   the string it self persists.

	static char * header;

	header = "  Center Heading For Report  ";

	....
	printf(header);	/* performs as expected */
	....

	header = "  Center Footing For Report  ";
	....

	printf(header);	/* yields a FOOTING as a Header ... OhMy! */

2) which brings up another storage class often forgotten altogeter:

	READONLY as in a format string given for printf()

	printf("text %c not of type %s\n" args, ..);

	xstr() collects said strings to reduce storage costs at possible
	expense of memory thrashing to get at a non-local page.

chris@mimsy.UUCP (Chris Torek) (08/08/88)

In article <12840@mimsy.UUCP> [and why does our netnews software use .UUCP?]
I wrote:
>>string constants ... do, however, have static storage duration ....

In article <255@quintus.UUCP> jbeard@quintus.uucp (Jeff Beard) writes:
>1) program scoped static char * foo may be altered anywhere by any procedure
>   and thus the original string reference will be lost to all, even though 
>   the string it self persists.
[example deleted]

Certainly.

>2) which brings up another storage class often forgotten altogeter:
>	READONLY as in a format string given for printf()

In the dpANS, read-only (called `const') is considered a `qualifier'
rather than a storage class.  Strangely, while "string"s are allowed
to be read-only, they have type `array of char' rather than `array of
const char'.  (I think this is a mistake.)

>	printf("text %c not of type %s\n" args, ..);
>	xstr() collects said strings to reduce storage costs at possible
>	expense of memory thrashing to get at a non-local page.

The xstr program actually collects *all* quoted strings, and replaces
each with something of the form `&xstr[<constant>]'.  This is annoying;
the common sequence

	#ifndef lint
	static char sccsid[] = "@(#)blort.c	4.2 (Berkeley) 8/8/88";
	#endif

fails to compile, since it becomes

	static char sccsid[] = &xstr[234];

One must write

	static char *sccsid = "@(#)blort.c	4.2 (Berkeley) 8/8/88";

which wastes a few bytes of storage per sccsid (since each id is
different).
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris