Static variable inside of a function in C - c

What will be printed out? 6 6 or 6 7? And why?
void foo()
{
static int x = 5;
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}

There are two issues here, lifetime and scope.
The scope of variable is where the variable name can be seen. Here, x is visible only inside function foo().
The lifetime of a variable is the period over which it exists. If x were defined without the keyword static, the lifetime would be from the entry into foo() to the return from foo(); so it would be re-initialized to 5 on every call.
The keyword static acts to extend the lifetime of a variable to the lifetime of the programme; e.g. initialization occurs once and once only and then the variable retains its value - whatever it has come to be - over all future calls to foo().

Output: 6 7
Reason: static variable is initialised only once (unlike auto variable) and further definition of static variable would be bypassed during runtime. And if it is not initialised manually, it is initialised by value 0 automatically.
So,
void foo() {
static int x = 5; // assigns value of 5 only once
x++;
printf("%d", x);
}
int main() {
foo(); // x = 6
foo(); // x = 7
return 0;
}

That is the same as having the following program:
static int x = 5;
void foo()
{
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
All that the static keyword does in that program is it tells the compiler (essentially) 'hey, I have a variable here that I don't want anyone else accessing, don't tell anyone else it exists'.
Inside a method, the static keyword tells the compiler the same as above, but also, 'don't tell anyone that this exists outside of this function, it should only be accessible inside this function'.
I hope this helps

6 7
compiler arranges that static variable initialization does not happen each time the function is entered

Output: 6,7
Reason
The declaration of x is inside foo but the x=5 initialization takes place outside of foo!
What we need to understand here is that
static int x = 5;
is not the same as
static int x;
x = 5;
Other answers have used the important words here, scope and lifetime, and pointed out that the scope of x is from the point of its declaration in the function foo to the end of the function foo. For example I checked by moving the declaration to the end of the function, and that makes x undeclared at the x++; statement.
So the static int x (scope) part of the statement actually applies where you read it, somewhere INSIDE the function and only from there onwards, not above it inside the function.
However the x = 5 (lifetime) part of the statement is initialization of the variable and happening OUTSIDE of the function as part of the program loading. Variable x is born with a value of 5 when the program loads.
I read this in one of the comments: "Also, this doesn't address the really confusing part, which is the fact that the initializer is skipped on subsequent calls." It is skipped on all calls. Initialization of the variable is outside of the function code proper.
The value of 5 is theoretically set regardless of whether or not foo is called at all, although a compiler might optimize the function away if you don't call it anywhere. The value of 5 should be in the variable before foo is ever called.
Inside of foo, the statement static int x = 5; is unlikely to be generating any code at all.
I found the address x uses when I put a function foo into a program of mine, and then (correctly) guessed that the same location would be used if I ran the program again. The partial screen capture below shows that x has the value 5 even before the first call to foo.

A static variable inside a function has a lifespan as long as your program runs. It won't be allocated every time your function is called and deallocated when your function returns.

Let's just read the Wikipedia article on Static Variables...
Static local variables: variables declared as static inside a function are statically allocated while having the same scope as automatic local variables. Hence whatever values the function puts into its static local variables during one call will still be present when the function is called again.

Vadiklk,
Why ...? Reason is that static variable is initialized only once, and maintains its value throughout the program.
means, you can use static variable between function calls.
also it can be used to count "how many times a function is called"
main()
{
static int var = 5;
printf("%d ",var--);
if(var)
main();
}
and answer is 5 4 3 2 1 and not 5 5 5 5 5 5 .... (infinite loop) as you are expecting.
again, reason is static variable is initialized once, when next time main() is called
it will not be initialize to 5 because it is already initialized in the program.So we can change the value but can not reinitialized. Thats how static variable works.
or you can consider as per storage: static variables are stored on Data Section of a program and variables which are stored in Data Section are initialized once. and before initialization they are kept in BSS section.
In turn Auto(local) variables are stored on Stack and all the variables on stack reinitialized all time when function is called as new FAR(function activation record) is created for that.
okay for more understanding, do the above example without "static" and let you know what will be the output. That make you to understand the difference between these two.
Thanks
Javed

The output will be 6 7. A static variable (whether inside a function or not) is initialized exactly once, before any function in that translation unit executes. After that, it retains its value until modified.

You will get 6 7 printed as, as is easily tested, and here's the reason: When foo is first called, the static variable x is initialized to 5. Then it is incremented to 6 and printed.
Now for the next call to foo. The program skips the static variable initialization, and instead uses the value 6 which was assigned to x the last time around. The execution proceeds as normal, giving you the value 7.

6 7
x is a global variable that is visible only from foo(). 5 is its initial value, as stored in the .data section of the code. Any subsequent modification overwrite previous value. There is no assignment code generated in the function body.

6 and 7
Because static variable intialise only once,
So 5++ becomes 6 at 1st call
6++ becomes 7 at 2nd call
Note-when 2nd call occurs it takes x value is 6 instead of 5 because x is static variable.

In C++11 at least, when the expression used to initialize a local static variable is not a 'constexpr' (cannot be evaluated by the compiler), then initialization must happen during the first call to the function. The simplest example is to directly use a parameter to intialize the local static variable. Thus the compiler must emit code to guess whether the call is the first one or not, which in turn requires a local boolean variable. I've compiled such example and checked this is true by seeing the assembly code. The example can be like this:
void f( int p )
{
static const int first_p = p ;
cout << "first p == " << p << endl ;
}
void main()
{
f(1); f(2); f(3);
}
of course, when the expresion is 'constexpr', then this is not required and the variable can be initialized on program load by using a value stored by the compiler in the output assembly code.

Share what I learned about this point.
In C static is a declaration specifier, which falls into three categories:
storage classes: there are four classes: auto, static, extern and register.
type qualifiers: like keywords: const, volatile, etc.
type specifiers: like keywords: void, char, short, int, etc.
So static is a storage classes. It will determine the following three properties of each variable in a C program.
storage duration: means when memory is allocated for the variable and when the memory is released. A variable with static storage duration stays at the same memory location as long as the program is running.
scope: means the portion of the program text in which the variable can be accessed.
linkage: means the extent to which the variable can be shared by different parts(or files) of a program.
The static storage class has a different effect on a variable depending on it is declared outside a block or inside a block. Let's focus on the case when a static variable declared within a block(the one discussed in this post).
A static variable in a block is initialized only once.
If a function is called multiple times, the static block variable is shared by all calls of the function.
This understanding is based on the book "c programming a modern approach"

Related

How do local static variables work in method?

Below is my code:
//main.c
int f()
{
static int x = 0;
x += 1;
return x;
}
int main()
{
f();
printf("%d", f());
}
and the output is 2.
I know that static variable will persist state, but since I called f() twice, each time x is set to 0 first (static int x = 0; ), then plus 1, then the output should be 1 regardless of how many times I call f()?
static variables not only persist, they are initialized once only, so x is not "each time set to 0 first", it remains 1 in the second call and then gets incremented. So indeed
static int x = 0; // x is initialized once only
is very different from
static int x;
x = 0; // x is set to 0 with every call
each time x is set to 0
No, you are reading the code incorrecly. The = here does not indicate assignment, rather it indicates initialization because its part of a declaration. The initial value of the variable is specified explicitly to 0. Static variables are only initialized once during a program's execution. If their declaration appears inside a function it doesn't change that behavior.
Also, an initializer for a static variable must be a constant expression (an expression that can be evaluated at compile time to a known value). This means that practically, an implementation doesn't need to introduce code to do any initialization inside the function. The value can be simply loaded into the storage of the variable at program startup.
You made two calls to f(), x has static storage duration, its lifetime is the entire execution of the program. This is why 2 is printed and not 1.
"...but since I called f() twice, each time x is set to 0 first (static int x = 0;),..."
No. x is not set to 0 each time f is called.
static variables are initialized only once at the first call to the function in which they are defined.
The special thing in comparison to automatic variables is that the memory object allocated persists until the end of the program.
The object as well as the value of x stays the same between different calls to the function f. So x is incremented by one at each call to the function without a reset to the once initialized value.
// Calls to f() in order
f(); // value of x at the end of the function: 1
f(); // value of x at the end of the function: 2
f(); // value of x at the end of the function: 3
f(); // value of x at the end of the function: 4
// and so on.
So, when you call f() twice, 2 is the correct value of x at the moment the function returns.
Side notes:
The explicit initialization of 0 is redundant. static variables are initialized to 0 by default.
The parameter list definition/declaration of a function in C should not be left omitted. Instead of int f(), write int f(void). int main() also should be edited to int main (void). int main() is obsolete.
Static variables can also be declared at local scope. static duration means that the object or variable is allocated when the program starts and is deallocated when the program ends. ( from here )
So what this means for your example program is that 2 is correct:
The following example code, coupled with the statement at top illustrates why:
Initial call:
static int x = 0; // unlike non-static variables, initialization is executed
// only once on 1st call to function.
// Also unlike non-static, local variables, locally created static
// variables are initialized to 0 automatically
// making the explicit assignment to 0 unnecessary.
// (although still a good habit. :))
...
x++; //x==1
2nd call:
static x = 0 //skipped
...
x++; //x==2
3rd call:
static x = 0 //skipped
...
x++; //x==3
And so on, until end of program...
(Having replaced x += 1; with its idiomatic shortcut syntax: x++;)

Selecting Static over Global. Why?

The output of the following code is 0.
int account=2;
int main()
{
static int account;
printf("%d",account);
return 0;
}
Why it picked static variable over global variable? Because what I understand is that both global and static variables are stored in the heap and not in function stack , right? So what method it uses to use select one over another?
If multiple variables exist with the same name at multiple scopes, the one in the innermost scope is the one that is accessible. Variables at higher scope are hidden.
In this case you have account defined in main. This hides the variable named account declared at file scope. The fact that the inner variable inside main is declared static doesn't change that.
While the static declaration on a local variable means that it is typically stored in the same place as a global variable, that has no bearing on which is visible when the names are the same.
Consider this small self explaining program:
#include <stdio.h>
int bar = 123; // global variable, can be accessed from other source files
static int blark; // global variable, but can be accessed only in the same
// source file
void foo()
{
static int bar; // static variable : will retain it's value from
// one call of foo to the next
// most compilers will warn here:
// warning declaration of 'bar' hides global declaration
printf("foo() : bar = %d\n", bar); // won't use the global bar but the
// local static bar
bar++;
}
void quork()
{
int bar = 777; // local variable exists only during the execution of quork
// most compilers will warn here as well:
// warning declaration of 'bar' hides global declaration
printf("quork() : bar = %d\n", bar); // won't use the global bar but the
// local bar
bar++;
}
int main() {
foo();
foo();
printf("main() 1 : bar = %d\n", bar);
bar++;
quork();
quork();
foo();
printf("main() 2 : bar = %d\n", bar);
printf("blark = %d\n", blark);
}
Output:
foo() : bar = 0
foo() : bar = 1
main() 1 : bar = 123
quork() : bar = 777
quork() : bar = 777
foo() : bar = 2
main() 2 : bar = 124
blark = 0
Just to clarify for future readers, global and static variables are not stored in heap or stack memory.
https://www.geeksforgeeks.org/memory-layout-of-c-program/
They will either be stored in initialized data or uninitialized data.
Thats not the main question here, which was answered by dbush, but it is a misunderstanding in the original question.
Short answer: encapsulation.
static describes both lifetime and visibility of a variable, and its meaning changes depending on the context. My opinion is that it is one of the more useful and important language features for encapsulation in c. Ignoring the complex relationship to extern, here's a simplified description:
static variables defined at the file level have program lifetime and compilation unit visibility. This means all functions in a .c file can access/modify the variable, but other .c files won't know about the variable. This is super useful for making sure variables used across functions with a compilation unit don't accidentally link with variables in other compilation units. Personally, I highly recommend all file variables to be static by default. Only remove the static specifier if you really want another compilation unit to have access to it (although a getter function may be safer)
Variables declared static within a block scope (most importantly function scope) have program lifetime, and scope visibility. That means it functions as if you declared the variable globally in the file, but only code within that block scope can see it. It also means from one call to the next, the variable does not get destroyed and state can be transferred from call to call.
One really important difference with static variables is that they are default-initialized to zero. This differs from all other variables in c, and is the reason your program prints the value 0. Often times with trivial programs we don't notice the difference because the stack hasn't been polluted with variables yet, but it becomes critical for any program of size.
The most common use for this that I have seen is to enable one-time initialization within a scope. They are also extremely useful for synchronization primitives like pthread_mutex_t. One time I even implemented a state-machine with function-scope static variable.
an example:
int started;//oops, anybody in the entire program can change this value, especially with such a common name!
static int lastCall;
int callCount(void)
{
// This is default-initialized to 0
static int functionStaticVariable;
//Increment each time I'm called
++functionStaticVariable;
//tell the outside world that I'm the one who was called last
lastCall = 1;
//return (a copy of) my internal state.
return functionStaticVariable;
}
char *getSharedMemory(unsigned int bytes)
{
// Here I cannot see functionStaticVariable, but I can see globalVariable
//functionStaticVariable++; // this would cause a compilation failure
// static pointer is default-initialized to zero (i.e. NULL)
static char *sharedMemory;
if(sharedMemory == 0)
{
// This block only executes once, the first time the function is called.
// Actually this is a nice side-effect because it means if the function is never called we don't clutter the stack with unused memory
// Although we will probably never free this memory
sharedMemory = (char *)malloc(bytes);
}
// tell the outside world that this function has been called
lastCall = 2;//valid
//Woah, this is such a bad idea, but actually does _not_ return memory that gets invalidated
return sharedMemory;
}
Hopefully you can see with this pattern you could protect a variable by placing it inside a function and doing optional things like acquiring a mutex-lock in order to allocate the memory. You could even implement the double-lock pattern this way.
I secretly wish that all C++ programmers learned good c encapsulation, because actually the language really encourages it. You can do an incredible amount by placing only functions that need to communicate with each other together in a compilation unit. In a non-OOP language, this can be very powerful.
Full details of static and extern are described by https://en.cppreference.com/w/c/language/storage_duration.
The pragmatic reasoning behind why innermost variable decaration should be the one used: you're not always in control of what's outside your code. You want to be able to write a function that certainly works. If other programmers (say, in a larger team) could break your code just by the way they name variables in other parts of the code, programming would be more of a pain than it is now.

Redeclaration of static variables in C... never happens?

I'm trying to fully understand how static variables work in C. I understand that using the static keyword makes the lifetime of the variable equal to the duration of the program. The following example has one thing that confuses me though...
My static_test.c file:
#include <stdio.h>
void foo(){
static int counter = 0;
counter++;
printf("This function has been called %i times.\n",counter);
return;
}
int main(){
int i;
for(i=0;i<10;i++){
foo();
}
return 0;
}
When I first read this example it makes me wonder why the function doesn't print out 0 every time since we are assigning 0 to the static variable.
Is this because once a static variable is declared the compiler ignores another declaration of the same variable on the next calls to my foo() function?
Thanks!
Despite the use of =, this is an initialization, NOT an assignment. So it happens when the variable is initialized and not when the 'statement' is apparently 'executed'. Since it is a static variable, it is initialized once when the program starts, rather than every time the function runs.
Static variables are initialized exactly once at program start, before your function is ever called. The fact that it's a local variable doesn't affect this rule.
In addition, static storage class variables are automatically initialized to zero if not explicitly initialized; the = 0 in your program is superfluous.
From the C11 drafts standard (ISO/IEC 9899:201x), section 6.2.4 Storage durations of objects, paragraph 3:
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.
Yes, the compiler looks for an initial assignment after declaring a static variable and only executes it once, when the program starts.
This only happens when you declare the variable though. For example,
void foo(){
static int counter;
counter = 0;
counter++;
printf("This function has been called %i times.\n",counter);
return;
}
Would print 1 every time.
Static means the variable exists outside of the life time of the function. Think of it as a slightly clever global variable.

Safe to pass pointer to auto variable to function?

Suppose I have a function that declares and initializes two local variables – which by default have the storage duration auto. This function then calls a second function, to which it passes the addresses of these two local variables. Can this second function safely use these pointers?
A trivial programmatic example, to supplement that description:
#include <stdio.h>
int adder(int *a, int *b)
{
return *a + *b;
}
int main()
{
auto int a = 5; // `auto' is redundant; included for clarity
auto int b = 3;
// adder() gets the addresses of two auto variables! is this an issue?
int result = adder(&a, &b);
printf("5 + 3 = %d\n", result);
return 0;
}
This program works as expected, printing 5 + 3 = 8.
Usually, when I have questions about C, I turn to the standard, and this was no exception. Specifically, I checked ISO/IEC 9899, §6.2.4. It says there, in part:
4
An object whose identifier is declared with no linkage and without
the storage-class specifier static has automatic storage duration.
5
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 is reached in
the execution of the block; otherwise, the value becomes indeterminate
each time the declaration is reached.
Reading this, I reason the following points:
Variables a and b have storage duration auto, which I've made explicit using the auto keyword.
Calling the adder() function corresponds to the parenthetical in clause 5, in the partial quote above. That is, entering the adder() function "suspends, but does not end," the execution of the current block (which is main()).
Since the main() block is not "end[ed] in any way," storage for a and b is guaranteed. Thus, accessing them using the addresses &a and &b, even inside adder(), should be safe.
My question, then, is: am I correct in this? Or am I just getting "lucky," and accessing memory locations that, by happenstance, have not been overwritten?
P.S. I was unable to find an exact answer to this question through either Google or SO's search. If you can, mark this as a duplicate and I'll delete it.
Yes, it is safe and basically your assumptions are correct. The lifetime of an automatic object is from the entry in the block where it has been declared until the block terminates.
(C99, 6.2.4p5) "For such an object [...] its lifetime extends from entry into the block with which it is associated until execution of that block ends in any way.
Your reasoning is correct for your particular function call chain, and you have read and quoted the relevant portions of the standard. This is a perfectly valid use of pointers to local variables.
Where you have to be wary is if the function stores the pointer values in a structure that has a lifetime longer than its own call. Consider two functions, foo(), and bar():
int *g_ptr;
void bar (int *p) {
g_ptr = p;
}
void foo () {
int x = 10;
bar(&x);
}
int main () {
foo ();
/* ...do something with g_ptr? */
return 0;
}
In this case, the variable xs lifetime ends with foo() returns. However, the pointer to x has been stored in g_ptr by bar(). In this case, it was an error for foo() to pass a pointer to its local variable x to bar().
What this means is that in order to know whether or not it is valid to pass a pointer to a local variable to a function, you have to know what that function will do with it.
Those variables are allocated in the stack. As long as you do not return from the function that declared them, they remain valid.
As I'm not yet allowed to comment, I'd rather write another answer as amendment to jxh's answer above:
Please see my elaborate answer here for a similar question. This contains a real world example where the aliasing in the called function makes your code break even though it follows all the c-language rules.
Even though it is legal in the C-language I consider it as harmful to pass pointers to automatic variables in a function call. You never know (and often you don't want to know) what exactly the called function does with the passed values. When the called function establishes an alias, you get in big trouble.

Why's initializing a global variable with return value of a function failing at declaration,but works fine at file scope?

An 80k reputation contributor R.. told me on SO that we can't initialize global variables with the return value of a function as that's not considered a constant,and global variables must be initialized with a constant.And true to his words,I get the following error for this program as expected-- initializer element is not a constant.Here is the program:
#include<stdio.h>
int foo();
int gvar=foo(); //ERROR
int main()
{
printf("%d",gvar);
}
int foo()
{
return 8;
}
But in this context,I just don't understand why the followed altered version of the above program shows no error at all and works fine.In this second program,I am initializing the same global variable with the return value of the same function foo().Can you tell me what is the rigorous technical reason for this variation in results?Why is initializing the global variable with the return value of a function at it's declaration causing error but the same initialization with the same return value works fine when done from within a function?
#include<stdio.h>
int foo();
int gvar;
int main()
{
gvar=foo();
printf("%d",gvar);
}
int foo()
{
return 8;
}
Output 8
The reason behind it is that in order to determine a value produced by a function one needs to execute code, and that there is no code execution done in C when initializing static and global variables.
Compiler and linker work together to prepare a byte image of the global memory segment: the compiler provides the values, and the linker performs their final layout. At runtime, the image of the segment is loaded in memory as is, without further modifications. This happens before any code gets executed, so no function calls can be made.
Note that this does not mean that it is not possible for some technical reason, only that C designers decided against doing it. For example, C++ compiler generates a code segment that calls constructors of global objects, which gets executed before the control is passed to main().
The second version doesn't have an initializer for gvar. gvar is declared and defined at global scope without an initializer. It has static storage duration, so it is initialized with zero.
The assignment in main is just that: an assignment, not an initialization.
In case 1, global variable is assigned with a variable while it is declared.
But in the second case, global variable is assigned(which is already declared) with return value of foo().
Forming of data section, text section all happens during compilation.
Global variables will be in data section(bss or initialized data section), so at compile time, foo() is not invoked right? and return value of foo() is not known during compilation.
But second case, when the text section get executed, gvar is assigned with return value of foo(). It is valid.
You can maybe think of it like this: when main() starts, all global variables must already have their initializer values. And they can't, as you've been told, get those by calling functions since main() is really where execution starts, in a C program.
we could not call any function from outer of the function.Not like shell script.function only allow to called from inside of function body.
In c first execution begins from main(), compiler don't know the function calling if that stands on outer of function it may taken as prototype if arg and return types provided.
we can putting return value of function by calling from main or others function block, to the variable,the function called then (that global) variable modified.
but we can use macro in global variable as needs.
as:
#define max() 12
int glob=max();
main()
{
}

Resources