By coincidence I stumbled over "The New C Standard" from Derek M. Jones, where he comments this sentence from the C99 standard regarding "storage duration of objects":
There are three storage durations: static, automatic, and allocated.
His comment:
One of the uses of the overworked keyword static is to denote objects that have static storage duration (there are other ways of denoting this storage duration).
The text marked bold is what irritates me. I've read this thread and this one, but it doesn't clarify it to me. Maybe my research is incomplete or I misunderstand his point...
I understand that the static
keyword is used to limit access to the file where the variable is declared, and I understand that those variables' lifetime is "unlimited" throughout the runtime of the program.
I also understand that some getter()
functions should be used to access those variables from other modules instead of tampering with extern
declarations.
And I understand the argument from @amon that
"
static
makes code untestable"
Btw, to overcome this, I've seen solutions where some construct like
#ifdef TESTING_ACTIVE
#define STATIC
#else
#define STATIC static
#endif
was introduced, having a compiler switch "-DTESTING_ACTIVE" for testing purposes.
Michael Barr says in his Embedded C Coding Standard:
The static keyword shall be used to declare all functions and variables that do not need to be visible outside of the module in which they are declared.
So... what exactly is Derek's problem with static
and what are those "other ways of denoting this storage duration" in C99?
2 Answers 2
The context of this paragraph is explaining storage duration, not the keyword static
. The parenthetical statement in question is just referring to the fact that there are many things with static storage duration that don't use the keyword static
.
For example, any file scope variable has static storage duration, despite not being marked with the keyword static
:
int x; // static storage duration, external linkage
static int y; // static storage duration, internal linkage
Static storage duration in this case is "denoted" by the variable's mere existence. Functions and string literals also have static storage duration without using the static
keyword (maybe other things too).
In fact, the only time static
actually means "static storage duration" is for local variables with no linkage:
void foo() {
int x; // automatic storage duration
static int y; // static storage duration
}
Giving static storage duration to local variables is in fact the original function of the static
keyword. The decision to reuse the same keyword for an unrelated purpose (that is, to modify linkage of file-scope variables) has caused a lot of confusion and is often considered to have been a mistake (hence the "overworked" comment in the original quote).
-
Hmmm... so the only "other way of denoting that storage duration" is to make the variable global by just not using static? And how else would I have internal linkage of file-scope variables without using static?mic– mic2021年05月28日 15:34:04 +00:00Commented May 28, 2021 at 15:34
-
@mic:
static
is the defined way to get file scope internal linkage.Robert Harvey– Robert Harvey2021年05月28日 15:37:21 +00:00Commented May 28, 2021 at 15:37 -
@RobertHarvey Yes, this was my understanding up to now, but trentcl seems to disagree. But regarding storage duration: Of course outside a function I don't have to declare a variable static to have static storage duration. However, I don't do this for that purpose, but to have internal linkage. So I still don't understand Derek's concern.mic– mic2021年05月28日 15:55:50 +00:00Commented May 28, 2021 at 15:55
-
@mic I'm not sure where you think I said there's another way of getting file scope internal linkage without using the
static
keyword (or perhaps I misunderstand your question). Elaborate?trent– trent2021年05月28日 15:57:38 +00:00Commented May 28, 2021 at 15:57 -
@trentcl Sorry... misunderstanding! I should really get some sleep :-D Of course you mean that "the decision ... is considered to have been a mistake", not the practice itself.mic– mic2021年05月28日 16:03:31 +00:00Commented May 28, 2021 at 16:03
The main problem with static
is that it destroys reentrancy - it’s why you can’t "nest" calls to strtok
. You only have a single instance of that object over the lifetime of the program. It is created and initialized once at program startup, and persists until program exit.
It can be confusing to read code like
void foo( void )
{
static int x = 5;
...
}
because x
only gets initialized to 5
once, before foo
is called, and then retains whatever value was last written to it between calls.
It’s all the heartburn of a global variable with extra confusion about scope and initialization thrown in for good measure.
-
Well, at least it doesn't throw in class hierarchies, copy constructors, or access functions. Imagine 30 years of that! (I jest, of course; that could never happen.)SO_fix_the_vote_sorting_bug– SO_fix_the_vote_sorting_bug2021年09月08日 09:28:46 +00:00Commented Sep 8, 2021 at 9:28
static
(i.e. making a global variable private) and more with the idea of global variables in general. Note that a global variable has static storage duration whether or not it's declared with the wordstatic
(they would've used the keywordprivate
but the C language designers thought that would be too easy)public
andprivate
keywords for scope usage, allowingstatic
to only be used for denoting persistent objects