I recently learnt about the static variables, that they retain their values in between various function calls. Then I wrote some code to test it, then hopefully it worked perfect. But then I accidentally removed the static keyword at the beginning of the declaration of the local variable and there came the actual problem.
The output of both the programs are similar, besides the absence of the static keyword during the declaration.
Code without any static declaration:
#include <stdio.h>
void up();
int main(){
up(); //Output: 1
up(); //Output: 2
return 0;
}
void up(){
int stvar;
stvar++;
printf("%d\n", stvar);
}
Code with static declaration:
#include <stdio.h>
void up();
int main(){
up(); //Output: 1
up(); //Output: 2
return 0;
}
void up(){
static int stvar;
stvar++;
printf("%d\n", stvar);
}
Then finally I tried this one, by just initializing the local variable:
#include <stdio.h>
void up();
int main(){
up(); //Output: 1
up(); //Output: 1
return 0;
}
void up(){
int stvar = 0;
stvar++;
printf("%d\n", stvar);
}
This time the local variable shows it natural behaviour.
I just wanted to know if uninitialized local variables are static by default?
No, they are not static by default. In principle, the initial value can be anything at all. Using the value could even be undefined behaviour. In practice, the compiler picks a memory location for the variable on the stack, and the variable's initial value is whatever happens to already be in that memory location.
Since you don't run any other code between the first up() and the second up(), in practice your program is likely to pick the same location twice and therefore it still has the previous value. If you called another function in between, that function's local variables would go in the same space previously used by up()'s local variables, which would overwrite the value from the first up().
You certainly can't rely on it. Even if you don't call any other functions in-between, the compiler might add one "secretly" (for various reasons). Or the compiler may decide to adjust the stack between the two calls to up so each call might get a different stack location for its local variables.
You also aren't guaranteed that the first value is 0. Because it's whatever happens to be at that memory location already, it could be something left over from a previous function. main isn't the first function that gets called; there is some function in the standard library which does set-up work before it calls main.
Using non initialized automatic variable is dangerous.
It is Undefined Behavior if no address is taken.
Otherwise, like in your case the value of stvar would be indeterminate. It's value can be arbitrary, it may even change between accesses.
Always initialize local variables.
Note that variables with static storage (globals and static) are zero initialized if not initialized explicitly.
Related
In C language, scope of the static variable through out the file.
In the following code, function returns the static variable.
int fun(){
static int i = 10;
return i;
}
int main() {
printf("%d\n", fun());
return 0;
}
And printed output 10.
So, Is returning local static in C undefined behaviour or well-defined?
You seem to have missed the whole logic for a return statement.
In this snippet, you are actually returning the value (of the variable), so, without the static storage also, the code is fine.
In case, you want to return the address of a variable, it needs to outlast the scope of the function. In that case, you need to have a variable with static storage, so that the returned address is valid (so that it can be used meaningfully from the caller function) even outside the function in which it is defined. So, either
you use a pointer returned by allocator functions, like malloc() or family
use the address of a variable defined with static storage class.
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.
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.
Hi can anyone tell me would variable a remain in memory or would it get destroyed immediately.
#include <stdio.h>
int main()
{
{
int a=1;
lab:
printf("Value of a : %d",a);
}
return 0;
}
would int a still remain in memory or not ?
Nope, a has local scope (declared between brackets) so at the closing brace it will be cleaned up.
If you want it to persist for the entirety of the program, either declare it as static or put it outside of any braces, preferably before you use it.
This has the added benefit of having the compiler initialise it for you.
You can try out the following:
#include <stdio.h>
int a;
int main()
{
static int b;
int c;
printf("%d, %d, %d\n", a, b, c); /* a and b should print 0, printing c is undefined behaviour, anything could be there */
return 0;
}
As Bathsheba pointed out, static variables should be used judiciously if used in a multi-threaded environment.
a is destroyed (popped from the stack) when you get to the } following the line with printf , so no, it does not remain in memory at your comment line.
First of all: It is not implementation specific. The C standard explicitly says, that leaving a block destroys an object with auto (local declared) lifetime:
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.
[ISO/IEC9899:TC3, 6.2.4, 5]
Of course, this is hard to test, because it loses it scope, too, in this case. (The other way around is easy to test.) But this is important for a formal reason: If you have a pointer to that object, which lives longer than the object, the program is always incorrect and the behavior is undefined – even an implementation let the object being alive. (Undefnied behavior includes that everything works fine.)
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()
{
}