When are LOCAL static variables initialized - c

I keep on seeing the same sentence that static variables are initialized only once, and I also saw a sentence stating that "when the block is entered for the first time".
Are local static variables initialized like other global variables - at the start of program execution? Or do local static variables differ from normal globals, and only get initialized once their function/block is called/reached?

C17 6.2.4 (3)
An object whose identifier is declared without the storage-class specifier _Thread_local, and either
with external or internal linkage or with the storage-class specifier static, has static storage duration.
Its lifetime is the entire execution of the program and its stored value is initialized only once, prior
to program startup.
However, remember the as-if rule. An implementation could wait to initialize the variable until the first call to the function, as a conforming program has no way to access its value before then, and so would not be able to tell the difference.
If you have an implementation with extensions or implementation-defined behavior that do provide a way to access the variable before the first call to the function, then such an implementation ought to document whether you would see the initialized value in such a case. In most cases I would expect the answer to be "yes".
The most common implementation I'm familiar with is to load the initial value from the executable, or to place it in a bss section that is zeroed at startup, just as is done for global or file-scope static variables.

Although implementation dependent, static variables - any scope - are initialized as the executable is loaded.

Related

Is it possible to access static local variable outside the function where it is declared?

For a static variable defined within a C function, like below:
int f1()
{
static int var2 = 42;
var2++;
printf("var2=%d\n", var2);
}
The var2 will be stored in the .data segment (because it is explicitly initialized to 42, thanks to #busybee pointing this out):
0000000000004014 l O .data 0000000000000004 var2.2316
The var2 will be stored in the .bss segment if I don't explicitly initialize it or initialize it to 0):
000000000000401c l O .bss 0000000000000004 var2.2316
There are 2 aspects about the var2:
Its lifetime is the same as the whole program.
But its scope is limited to within f1().
The bss section is meant for uninitialized global data. While the data section is meant for initialized global data. The var2 lives in bss so it must be global in a sense.
I think the reason that var2 can only be accessed within f1() is just some syntactical rule placed by the compiler. If we iterate through the bss section, the var2 must be accessible from outside the f1(). Am I right on this? Thanks.
Well you have raw access to memory, so the world's your oyster, but their limited access scope is exactly the whole point of using static local variables.
They're global state with controlled access, so you can apply local reasoning.
If you can access them externally, then local reasoning goes out the door. At that point, one should think: why not just use a regular global?
The following is more or less hacker stuff, in addition to other answers, not from the viewpoint of a language lawyer.
I think the reason that var2 can only be accessed within f1() is just some syntactical rule placed by the compiler.
To be picky, this is true only if the compiler is compliant to the standard. ;-) It is the standard that defines the rule. The technical term is "scope".
If we iterate through the bss section, the var2 must be accessible from outside the f1(). Am I right on this?
Yes. The section exists as long as the program runs. You can use a pointer into this section and access any variable living there. This holds true for the data section, too, of course.
You can also use a pointer to access any dynamic variable. Commonly these are allocated on the stack. To get a grip on a specific value can be quite tricky, though.
But all these accesses are application specific, compiler dependent, and system dependent, at least. You will probably break some rules. But in principle, nothing can stop you.
The bss section is meant for uninitialized global data. While the data section is meant for initialized global data.
This is only true if you mean "explicitly initialized to non-zero values".
Both sections are initialized before main() starts. All values in bss are zeroed, and all values in data are set to their non-zero values. A variable explicitly initialized to a zero value will commonly be allocated in bss.
The reason for the existence of separate sections is to save space in the executable. The bss section is commonly not stored, it is only defined. It does not makes sense to store a whole bunch of zeroes, the startup code will zero the complete section.
The var2 lives in bss
var2 does not live in the bss segment, but in the data segment, as the cutout clearly shows. Your var is initialized with 42, which is apparently non-zero.
Two execution environments are defined: freestanding and hosted. In
both cases, program startup occurs when a designated C function is
called by the execution environment. All objects with static storage
duration shall be initialized (set to their initial values) before
program startup. The manner and timing of such initialization are
otherwise unspecified. Program termination returns control to the
execution environment.
An object whose identifier is declared without the storage-class
specifier
_Thread_local, and either with external or internal linkage or with the storage-class specifier static, has static storage duration. Its
lifetime is the entire execution of the program and its stored value
is initialized only once, prior to program startup.
Your static local variable has static storage duration and will be initialized before program execution starts (ie before main is called). You can access it via a pointer to it. The pointer can be only obtained by calling the function.
int *func()
{
static int x;
return &x
}
There are 2 aspects about the var2:
Its lifetime is the same as the whole program.
But its scope is limited to within f1().
Yes and no. Lifetime is a property of objects. Scope is a property of identifiers (names). That the scope of var2 is from its declaration in f1() to the end of the function is about the region of the source wherein that name identifies the object in question. On the other hand, that the lifetime of the object identified by var2 inside that scope is the same as the whole program's is about the object itself.
The bss section is meant for uninitialized global data. While the data section is meant for initialized global data. The var2 lives in bss so it must be global in a sense.
Be very careful about trying to infer language semantics from implementation details. It is very easy to get that wrong, and very hard to get it right in all details. In this particular case, the object in question is global in exactly the sense that its lifetime is the same as the whole program's, which you already knew.
For the record, "global" is not a C-language term. When people say "global variable" in C context, they usually mean a variable more properly described as having external linkage, which necessarily identifies an object having static storage duration (i.e. the whole execution of the program). That's not what you're looking at in the case of var2.
I think the reason that var2 can only be accessed within f1() is just some syntactical rule placed by the compiler.
More or less yes. The object can be accessed by name only within the scope of that name. This is among the semantic rules of the C language. It is essentially the definition of "scope".
If we iterate through the bss section, the var2 must be accessible from outside the f1(). Am I right on this?
How do you propose to "iterate through the bss section"? In the first place, that's a characteristic of some executable file formats, not a runtime characteristic of the program. But perhaps you mean "iterate through memory", but even then, C does not define a way to do that.
With that said, if f1() published a pointer to its var2 variable, via an out variable, for example, that pointer could indeed be used outside the function to access that object. Like this, for example:
int f1(int **pptr) {
static int var2 = 42;
*pptr = &var2;
var2++;
return printf("var2=%d\n", var2);
}
// ...
void other_function() {
int *ptr;
int res = f1(&ptr);
printf("%d\n", *ptr);
}

how does a static variable not get reassigned when inside the function

I have a question regarding the answer in this question but I can not comment on it because I have less than 50 rep.
I was wondering in the answer foo() is being called multiple times and the static variable is being assigned the same number of times. So why is it that the static variable is not reassigned to 10 each time?
You've got the shorter answer, but let me expand a bit on that.
Any object, has a storage duration. The storage duration determines the "lifetime" of the object (or variable).
Static storage is one of the storage durations, marked by keyword static. Now, to elaborate on lifetime, let us check the relevant parts of the C11 standard, chapter §6.2.4.
From paragraph 2,
The lifetime of an object is the portion of program execution during which storage is
guaranteed to be reserved for it. An object exists, has a constant address and retains
its last-stored value throughout its lifetime. [....]
So, the last stored value is retained throughout the lifetime.
Now, for the objects with static storage duration, paragraph 3,
An object whose identifier is declared without the storage-class specifier
_Thread_local, and either with external or internal linkage or with the storage-class
specifier static, has static storage duration. Its lifetime is the entire execution of the
program and its stored value is initialized only once, prior to program startup.
Now, referring to your question, the statement you saw is the initialization and as per the rule specified, it happens only once (prior to program startup), so the initialization is not repeated over for multiple function calls. The variable retains the last-stored value.
Actually static variables can get reassigned. But can't be redefined.
Once a static variable defined it can't get redefined throughout the life time of program. But we can change the value.
When you define a static or global variable it goes in data segment of memory model and it occupies that allocation for the life of the program, of course scope is associated with each variable where it is defined. So when you enter the function again, the variable exists and it also remembers the last content. So ideally you cannot redefine a variable, if you bound it with condition than scope will protect it and hence it is a new variable.

Static variable in a function called repeatedly C

I am writing a function which is meant to be called multiple times, where I want to have a static pointer to the beginning of a list. I need the function, no matter how many times it is called, to access the same list, so I have two questions.
Am I right that if I declare it static t_line *begin = NULL; where t_line is my struct, I believe it will already have allocated the correct space before main() is called, as I understand static variables do, then this will give me a null pointer with the correct allocated size.
Once I give that static pointer the address of the first element in my list, the next time the function is called and it reaches that declaration line, wouldn't it just reset it to NULL and I'd lose my pointer?
Variables with static storage are initialized only once, you're good to go.
Quoting C11, chapter §6.2.4, emphasis mine
An object whose identifier is declared without the storage-class specifier
_Thread_local, and either with external or internal linkage or with the storage-class
specifier static, has static storage duration. Its lifetime is the entire execution of the
program and its stored value is initialized only once, prior to program startup.
That said, regarding retaining the last-stored value, quoting paragraph 2, (again, my emphasis)
The lifetime of an object is the portion of program execution during which storage is
guaranteed to be reserved for it. An object exists, has a constant address,33) and retains
its last-stored value throughout its lifetime.34) [....]
and, for static variables, as mentioned above
Its lifetime is the entire execution of the
program

Assignment to static variable is ignored

I have following piece of code:
#include <stdio.h>
int f1()
{
static int s=10;
printf("s=%d\n",s++);
}
int main()
{
f1();
f1();
return 0;
}
The output is:
s=10
s=11
Why is the line static int s=10 ignored at the second time, when f1 is called?
That is no assignment, but an initializer. Local static variables are only initialized once at program startup like global variables. They keep their last assigned value even between invocations of the function. Thus after your first call, it retains the value 11. In fact, they are like file-scope static variables, with their name only known in the scope of the block they are declared (but you can pass them by pointer).
Drawback is they only exist once. If you invoke the same function from multiple threads, they all share the same variable.
Try a third call: you will get 12.
Note: the initializer must be a constant expression. Try static int s = 10, t = s + 5; and read the compiler error message.
Initialization of a static variable is one-time (with the time of initialization guaranteed to occur before the first call, which could occur at compile time or at run time; compiler dependent). That's the main reason to use them.
The static variables are initialized only once, conceptually even before application has started.
From C11 (N1570) §5.1.2/p1 Execution environments:
All objects with static storage duration shall be initialized (set to
their initial values) before program startup.
along with §6.2.4/p3 Storage durations of objects:
Its lifetime is the entire execution of the program and its stored
value is initialized only once, prior to program startup.
As others have said, a static variable at function scope is initialized only once. So the assignment doesn't happen on subsequent calls to the function.
Unlike other local variables, a static local is not defined on the stack but in the data segment, probably in the same location as global variables. Globals are also initialized at application startup (they have to, since they don't live inside of a function and therefore can't be executable code), so conceptually you can think of a static variable as a global variable with limited visibility.
From the C89 Standard HTML version at 3.1.2.4 Storage durations of objects it specifies:
An object declared with external or internal linkage, or with the storage-class specifier static has static storage duration. For such an object, storage is reserved and its stored value is initialized only once, prior to program startup. The object exists and retains its last-stored value throughout the execution of the entire program
(The emphasis is mine)
So it says that everytime you use the static qualifier, that variable preserves its value across multiple function calls.
Local variables that are not static are initialized everytime you call the function that delcares them, so they do not preserve their value across function calls.
Hope this helped!

different types of Static in C

I know there are three types of static declerations in C:
1: Constant - constant static variable, ex: static const int i = 5;
2: Changable - just a normal static variable, ex: static int hi = 10;
Here is my question
There is another form of static which takes the form of "code". What does that mean and can you give me an example?
Thank you!
EDIT:
Are static/const variables stored on the stack/heap?
Maybe you are talking about a static function ?
This is a specific use of the word "static", which is entirely different from a static variable.
When you declare a function "static", that means it cannot be linked from another source file. It is typically used to keep some functions "private".
[Edit] Note that, in theory, the function code could still be accessed from another source file using pointers, but that's not quite the normal way (and certainly not the easiest) to access a function. Thanks to Eric Postpischil for pointing that out.
It's unfortunate that the same word "static" is used in the C standard to mean two different things, depending on being used for functions or variables.
[edit] : It's a different question, but anyway : in the case of static variables, they are neither allocated in the heap nor the stack. They are, well, static, which means they are allocated in a static space, directly allocated by the compiler at startup. Stack is for internal functions variables, and heap is for malloc()/free().
This link should answer your question.
It is however worth noting that unless you have sufficient knowledge of the C compilation process this will be of questionable value.
A good reference for GCC can be found here.
I believable you're asking about static functions.. So..
Static functions
By default, functions in C are extern, meaning that the function can be used in any other file of the same project (and the same code of course).
If you don't like this situation and you want to limit the function to the file in which it's defined, you make it static.
The keyword static is used in several different ways in C. (There's a joke that any new version of the ISO C standard is required to invent a new meaning for static.)
Quick summary: The static keyword on a block scope definition gives the entity static storage duration; at file scope, where definitions already have static storage duration, it instead gives them internal linkage.
An object may have any of several storage durations. An object with "automatic" storage duration exists at run time only during the execution of the enclosing block. An object with "static" storage duration exists during the entire execution of the program. (There are also "allocated" and, new in C11, "temporary" storage durations, which I won't get into.)
Any definition of an identifier also has a "linkage", which can be external, internal, or none. Linkage controls whether an identifier is usable across translation units (basically source files, but #included files are not separate translation units). Linkage, as the name implies, has to do with the linker. You can use the same identifier with internal linkage in two different source files, and it will refer to two different entities. But if an identifier has external linkage, it should be defined only once, and can be declared (typically with extern) in multiple source files; all those declarations will refer to the same entity.
If you define an object (variable) at block scope, (i.e., inside a function body), it has automatic storage duration (and no linkage) by default. Adding the keyword static gives it static storage duration, so it exists and retains its value across calls to the function. (It doesn't affect the identifier's visibility).
If you define an object at file scope (i.e., outside any function body), it has static storage duration and external linkage by default. Adding the keyword static to the definition doesn't affect its storage duration, but it changes its linkage from external to internal, hiding the name from other translation units. Functions don't have storage duration (their code exists as long as the program is running), but static affects their linkage the same way, changing it from external to internal.
(C99 added another meaning for static, for function parameters of array type, which has nothing to do with the other uses.)
I think it's worth to clarify what we're talking about and try to use the correct wording.
The const qualifier has nothing to do with the static keyword.
Technically, the static keyword appears in declarations and it's usually a storage-class specifier, but from C99 it can also be in array declarators, though this is quite unusual.
When it's a storage-class specifier, just like in the declarations you've posted, it affects the linkage (visibility between files) of the identifier and the storage duration (lifetime) of the identified object, but not the scope of the identifier.
6.2.2 Linkages of identifiers
[...] Within one translation unit, each declaration of an identifier with internal linkage denotes the same object or function. [...]
If the declaration of a file scope identifier for an object or a function contains the storage-class specifier static, the identifier has internal linkage.30)
30) A function declaration can contain the storage-class specifier static only if it is at file scope; see 6.7.1.
Therefore, the identifier can only be seen in the translation unit (i.e., a source file after the preprocessing) where it's declared, whether it's an object or a function (maybe that's what you were looking for). So you can use to declare "private" functions to be used in just one file.
static void foo(void)
{
// ...
}
The static keyword it's also used with the inline function specifier, which has a particular linkage semantics: https://stackoverflow.com/a/216546/1202636
Obviusly when we are not at file scope but in a more restricted one (static declarations inside functions) the linkage question becomes irrelevant since such an identifier has no linkage at all.
6.2.4 Storage durations of objects
An object whose identifier is declared [...] either with external or internal linkage or with the storage-class specifier static, has static storage duration. Its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup.
This one only applies to object identifiers and it affects the lifetime of the object, for example letting a variable retains its value between calls, and its initialization.
(just to say it, such an object is also initialized with a default value)
As I said, there's a less common use of the static keyword: it can be use in array declarators inside function prototypes, to tell the compiler that an array given as parameter contains at least n elements. This is a (modified) example from the standard:
void f(double a[static 3][5]);
The declaration specifies that the argument corresponding to a in any call to f must be a non-null pointer to the first of at least three arrays of 5 doubles, which the others do not.
.
Are static/const variables stored on the stack/heap?
Again, the constness has nothing to do with the place where an object is stored. The standard doesn't say anything about that place, there's usually a dedicated area but this is a different and already answered question: where are static buffers allocated?
Are static/const variables stored on the stack/heap?
Well, no, they are part of the "global" space.
Stack and Heap are for "dynamic" memory allocation, not static !

Resources