Static variable in a function called repeatedly C - 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

Related

When are LOCAL static variables initialized

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.

How do static variables in C persist in memory?

We all know the common example to how static variable work - a static variable is declared inside a function with some value (let's say 5), the function adds 1 to it, and in the next call to that function the variable will have the modified value (6 in my example).
How does that happen behind the scene? What makes the function ignore the variable declaration after the first call? How does the value persist in memory, given the stack frame of the function is "destroyed" after its call has finished?
static variables and other variables with static storage duration are stored in special segments outside the stack. Generally, the C standard doesn't mention how this is done other than that static storage duration variables are initialized before main() is called. However, the vast majority of real-world computers work as described below:
If you initialize a static storage duration variable with a value, then most systems store it in a segment called .data. If you don't initialize it, or explicitly initialize it to zero, it gets stored in another segment called .bss where everything is zero-initialized.
The tricky part to understand is that when we write code such as this:
void func (void)
{
static int foo = 5; // will get stored in .data
...
Then the line containing the initialization is not executed the first time the function is entered (as often taught in beginner classes) - it is not executed inside the function at all and it is always ignored during function execution.
Before main() is even called, the "C run-time libraries" (often called CRT) run various start-up code. This includes copying down values into .data and .bss. So the above line is actually executed before your program even starts.
So by the time func() is called for the first time, foo is already initialized. Any other changes to foo inside the function will happen in run-time, as with any other variable.
This example illustrates the various memory regions of a program. What gets allocated on the stack and the heap? gives a more generic explanation.
The variable isn't stored in the stack frame, it's stored in the same memory used for global variables. The only difference is that the scope of the variable name is the function where the variable is declared.
Quoting C11, chapter 6.2.4
An object whose identifier is declared [...] 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.
In a typical implementation, the objects with static storage duration are stored either in the data segment or the BSS (based on whether initialized or not). So every function call does not create a new variable in the stack of the called function, as you might have expected. There's a single instance of the variable in memory which is accessed for each iteration.

When will stack memory be reallocated?

There is code like the following:
int fun(){
char* pc = NULL;
{
char ac[100] = "addjfidsfsfds";
pc = ac;
}
...
pc[0] = 'd';
printf("%s\n", pc);
...
}
So, can I use pc safely after the scope of ac ends? Because I'm not sure whether the stack memory allocated for ac will be reallocated by the compiler for other usage or not.
The defect in understanding you have has to do with the Storage Duration of Objects. Unless you are working with threads, you have three types to be concerned with, static, automatic, and allocated. By declaring char ac[100] = "addjfidsfsfds"; within the block and without the static storage-class specifier, the storage duration is automatic and its lifetime ends when execution of the bock ends. Attempting to access the value afterwards is Undefined Behavior.
The C-Standard lays this out in detail in section 6.2.4, e.g.
C11 - 6.2.4 Storage durations of
objects
1 An object has a storage duration that determines its lifetime. There
are four storage durations: static, thread, automatic, and
allocated. Allocated storage is described in
7.22.3.
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,33) and retains its last-stored value
throughout its lifetime.34) If an object is referred to outside of its
lifetime, the behavior is undefined. The value of a pointer
becomes indeterminate when the object it points to (or just past)
reaches the end of its lifetime.
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.
( _Thread_local details omitted)
5 An object whose identifier is declared with no linkage and without
the storage-class specifier static has automatic storage duration, as
do some compound literals. The result of attempting to indirectly
access an object with automatic storage duration from a thread other
than the one with which the object is associated is
implementation-defined.
6 For such an object that does not have a variable length array
type, its lifetime extends from entry into the block with which it is
associated until execution of that block ends in any way. (Entering
an enclosed block or calling a function suspends, but does not end,
execution of the current block.) If the block is entered recursively,
a new instance of the object is created each time. The initial value
of the object is indeterminate. If an initialization is specified for
the object, it is performed each time the declaration or compound
literal is reached in the execution of the block; otherwise, the value
becomes indeterminate each time the declaration is reached.
7 For such an object that does have a variable length array type,
its lifetime extends from the declaration of the object until
execution of the program leaves the scope of the declaration.35) If
the scope is entered recursively, a new instance of the object is
created each time. The initial value of the object is indeterminate.
If there is ever a question about whether accessing a value is allowed or not, consult the standard.
From C Standard#6.2.1p4 [emphasis mine]
Every other identifier has scope determined by the placement of its declaration (in a declarator or type specifier). If the declarator or type specifier that declares the identifier appears outside of any block or list of parameters, the identifier has file scope, which terminates at the end of the translation unit. If the declarator or type specifier that declares the identifier appears inside a block or within the list of parameter declarations in a function definition, the identifier has block scope, which terminates at the end of the associated block. ......
Variable ac is a local(automatic) non-static variable and its lifetime is limited to its scope i.e. the block in which it has been declared. Any attempt to access it outside of its lifetime lead to undefined behavior.
From C Standard#6.2.4p2 [emphasis mine]
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) If an object is referred to outside of its lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.
Using pc outside the inner scope is unsafe in your example. Because ac is destroyed right after pc = ac, you have a classic dangling pointer. With sufficient warnings enabled, I assume most compilers will emit warnings.
This may appear to work on your system, but that doesn't mean it's safe. Some compilers may choose to perform reclaim all primitives at once as an optimization, but they're not required to do that.
It may be reallocated after the end of the block (when it goes out of scope).
Whether it will be reallocated varies, depending on the program and on the architecture of the machine on which it's running (and the compiler).
It's likely to be reallocated when you declare another local variable (on the stack); and/or, when you make a function call (which pushes parameter values and a return address onto the stack, and lets the called function declare new variables).
It's theoretically possible it may be reallocated at a pseudo-random time, by a hardware interrupt or similar. In some implementations an interrupt service handler (which might run at any time) starts by saving the current machine state on the stack.

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.

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!

Resources