Why uninitialized local variable always has the same initial value? - c

In this piece of code, why in my testing the result is always 1, 2, and 3?
#include <stdio.h>
void test() {
int a;
a++;
printf("%d",a);
}
int main(int argc, char *argv[]) {
test();
test();
test();
}
I think the variable in test() is static, isn't it? And Why?

The variable is not static. You're accessing an uninitialized variable. The behavior is undefined.

As other answers told, your variable is not initialized.
It prints 1, 2 and 3 possibly because of your compiler compiled the code with prolog(prologue) that cleans the stack with zeros.
The local variables in C, actually point to the offset on your stack, and the stack frame will be restored after the call is returned.
I googled and selected a artical randomly that told about this, see [How function calls work?].
Here is a video talk about that [Assembly Programming Assembly Function Stack Frame Explained ] (again, selected randomly).
And Wikipedia explains the [Call stack] as well.

Because you are working with an unintialize value... (random behaviour in this case).
Initialize your variable (example to 0) :
#include <stdio.h>
void test(){
int a=0;
a++;
printf("%d",a);
}
int main(int argc, char *argv[]) {
test();
test();
test();
}

No, your variable is not static at all!
https://stackoverflow.com/a/1597426/1758762
Static variables (file scope and function static) are initialized to zero:
int x; // zero
int y = 0; // also zero
void foo() {
static int x; // also zero
}
Non-static variables (local variables) are indeterminate. Reading them prior to assigning a value results in undefined behavior.
void foo() {
int x;
printf("%d", x); // the compiler is free to crash here
}

the variable you are trying to print is not static and neither it is initialized , thus it is taking garbage value , which seems random to you , if you execute this program on a different machine ,then there you will have different output because there you will have different garbage value
in order to avoid it , you will have to initialize your variable with some value

Related

Change random memory location on purpose between two executions in c

I sometimes want to show my students that local variables have to be initialized before use. But on some occasions they get the initial value of zero without being initialized. So my students don't believe me. For example in this code.
#include <stdio.h>
int main(void){
int sum;
sum += 5;
printf("%d", sum);
return 0;
}
Sometimes output is 5. To demonstrate the undefined behaviour of not initialising the variable sum to zero I am looking for an example.
Pointing to standards is good. But I understand your desire to show an example to your students. I'm not sure about the best way; but to increase your chances of seeing the undefined behavior, you can declare multiple variables that cannot easily be optimized away by the compiler.
#include <stdio.h>
void main(){
int sum1;
int sum2;
int sum3;
int sum4;
int sum5;
int sum6;
int sum7;
int sum8;
int sum9;
int sum=sum1+sum2+sum3+sum4+sum5+sum6+sum7+sum8+sum9;
printf("%d\n",sum);
}
On my system; recent Ubuntu, with recent GCC this produces incorrect results on every run, whereas your original example always produced 5. But I can't make any guarantees for your system.
Memory is usually initialized to zero when a process is started. Otherwise, you would get old memory contents from another process, which would be a security risk. Because of this, code like this will, in my experience, usually print zero:
#include <stdio.h>
int main(void) {
int x;
printf("%d\n", x);
}
You have a greater chance to get non-zero results if you use memory that has been used by your own process. For example, I just got non-zero printouts with this program:
#include <stdio.h>
void f(void) {
int x;
printf("%d\n", x);
}
int main(void) {
f();
f();
f();
}
But remember that according to the standard, the contents of an uninitialized local variable (with storage class auto) is undefined, so a compiler is allowed to always set its variables to zero. Or -4.
How about explicitly setting the value for a certain position and reading it from another uninitialized variable pointing at the same position?
#include <stdio.h>
void foo()
{
int x = 1234;
}
void bar()
{
int y;
printf("%d\n", y);
}
int main()
{
foo();
bar(); /* Will print out 1234 */
}
It would be better to not prove your students something by your self instead use C standards.
C99 section 6.7.8 Initialization:
If an object that has automatic storage duration is not initialized
explicitly, its value is indeterminate.

Is it possible for a variable in a function to hold an old value from old calls of the function in C?

I'm having something like this:
void test(int iter){
int i;
if(iter>3){
i=5;
printf("%d",i);
}else{
printf("%d",i);
}
return;
}
int main(){
test(5);
test(2);
return 1;
}
This is just for example. Is it possible when called by main variable i hold value of 5 (in memory) if at least iter is greater than 3?
I know that it is not normal. But I have a function in my program (I don't have static var that is doing this) which does it. So maybe the address where this variable is initialised each time the same (so I'm getting the old value)? Or what does happen? I don't want to hold the old value or something. I'm just curious: how is this possible?
If i is stored at some location on the stack, and if that location is not modified, then i will retain it's value.
Assuming that i is even stored on the stack (optimization may eliminate this), if there is an interrupt that uses the stack (or perhaps a context switch due to time slice), the stack area below the stack pointer will get overwritten. Some compilers may fill in the stack area, usually in debug mode. Visual Studio in debug mode will catch the usage of an uninitialized variable with the above code.
In this example you are showing us, you never initialize i with a value, and it is never assigned a value unless iter is > 3.
Its value is undefined until you actually set it to something, which you only do in the "if" part of your "if then else" clause.
So it's perfectly normal that you might have a garbage value in i when iter is 3 or less.
Declear your variable Global (out of function).
for example:
int a=0;
void f(){
a++;
}
this way the value will not be lost after execution of function.
Do this:
void test(int iter){
static int i;
if(iter>3){
i=5;
printf("%d",i);
}else{
printf("%d",i);
}
return;
}
int main(){
test(5);
test(2);
return 1;
}
Note the static keyword in the static int i; line.

Use of automatic variable outside its scope in C [duplicate]

This question already has answers here:
What happens when a variable goes out of scope?
(3 answers)
Closed 6 years ago.
I am studying the working of an automatic variable. I know that it is only accessible inside the block or function in which it is declared and its lifetime is within that same function or block. So the following piece of code I am trying to check.
/Declaration of header files/
void testfn(void);
int *p;
int main(void)
{
testfn();
print("%d\n",*p);
return 0;
}
void testfn(void)
{
int x=444;
p=&x;
}
The output is - 444
I am wondering that when the testfn(); exits,the variable x will be destroyed. Then how in main function the pointer (*p) prints 444.
How this works...or if I am missing something.
Please clarify my doubt.
Thanks
It is coincidence that the original value still remains. With another compiler, or with another compilation configuration, it could take any other value or the program could just crash.
If between the testfn and printf functions you call any other function that does something with its local variables, you might see that the 444 value is not obtained anymore. But this is just, again, coincidence.
p points to the stack where x was stored. If the memory location hasn't been used for something else you will most likely get 444.
Try to insert another function call before printing p and see what happens:
#include <stdio.h>
#include <math.h>
void foo() {
int y=123;
}
void testfn(void);
int *p;
int main(void)
{
testfn();
foo();
printf("%d\n",*p);
return 0;
}
void testfn(void)
{
int x=444;
p=&x;
}
On my machine, the output is now:
123
Since the code results in undefined behaviour, the result could be different if I try this on another platform. But you can see that undefined behaviour can lead to strange bugs.
The memory location that was previously reserved for variable x is not overwritten yet. But it may be at any time. That's why your code leads to undefined behaviour.
In the following example, the memory location that was previously reserved for variable x will be overwritten by the value that is assigned to the variable y. Since the pointer p still points to that location, *p will evaluate to this new value:
#include <stdio.h>
int *p;
void test1(void) {
int x = 444;
p = &x;
}
void test2() {
int y = 15;
}
int main(void) {
test1();
test2();
printf("%d\n",*p);
return 0;
}
The fact that the value still remains is completly coincidental (not guaranteed) because nothing has overwritten it yet.
You can not count on this, it may fail, may print garbage or may crash your program or pc even.
Don't use this, it is considered undefined behavior.

What is the difference between two sets of code writen below

#include<stdio.h>
int *fun();
main()
{
int *i;
i=fun();
printf("cbgg\n");
printf("%d",*i);
getch();
}
int *fun()
{
int k;
k=5;
return (&k);
}
Though the program written above prints a garbage value for i, yet the the program written below works fine,i.e. the output is absolutely relevant, which is 5. Why is this so?
#include<stdio.h>
int inc();
main()
{
int i;
i=inc();
printf(“cbgg\n”);
printf(“%d”,i);
getch();
}
int inc()
{
int k;
k=5;
return (k);
}
The main difference is that this one does a pretty nasty thing by returning the address of a local variable (allocated on the stack) - Later usage of the returned pointer calls for undefined behavior.
int *fun()
{
int k;
k=5;
return (&k);
}
The other one is just a harmless return of 5 from the fun() routine.
To understand this you need to know a little bit about how arguments are passed to and from functions. When "fun" is called the arguments to "fun" are pushed on the stack (among other things). For "fun" to return values it pushes them on the stack and the caller later pops the value.
The local variable int k has function scope so when the function "fun" exits the stack space used is destroyed. Returning a pointer to that destroyed memory area is undefined behavior and that is what you are doing when you return &k. In #2 you instead push the value of k on the stack and that is valid.
In first case you are returning pointer to local variable,whose scope is limited to function only.
Whenever you return from function stack gets modified and you get unexpected data.

Automatic Storage class

Automatic Storage used in a function does not re-initialize the i variable declared using the auto keyword.
Practice.c : main() and func() are in the Practice.c
#include <stdio.h>
main()
{
func();
func();
func();
}
func()
{
auto int i=1;
printf(" i = %d",i);
i=i+1;
}
After compilation when I execute Practice.exe the output is as follows :
i = 1
i = 1
i = 1
Every time main() calls func() i is re-initialized to 1. This is correct as scope of i is within the func() block, and when the control comes out of this block the value of i is lost. So, when I will be calling this func() function for the second time the value of i will be re-initialized to 1.
Check the following New.c Program.
New.c : contains both main() & func()
#include <stdio.h>
main()
{
func();
func();
func();
func();
func();
func();
func();
func();
}
func()
{
auto int i;
printf(" i = %d",i);
i=i+1;
}
Just to be sure, I called the function func() 8 times.
But in New.c, i is not initialized. When I executed this program after compilation, the output of it is as follows :
i = 4201582
i = 4201583
i = 4201584
i = 4201585
i = 4201586
i = 4201587
i = 4201588
i = 4201589
The output shows increment on every call. What is the exact reason behind this ?
The output shows increment on every call. What is the exact reason
behind this ?
Variables with automatic storage allocation are not initialized by default and it is undefined behaviour to access an uninitialized variable. This means the behaviour of your second program cannot be reasoned out.
Also, note that the default stororage class of variables in function scope is automatic. Therefore, you don't need the auto keyword to qualify the definition of i.
// in function scope
auto int i;
// equivalent to
int i;
Also, it's wrong to say
So, when I will be calling this func() function for the second time
the value of i will be re-initialized to 1.
The variable i is not re-initialized. It goes out of scope once the function containing it returns. When the function is called again, it's again allocated on the stack. This does not mean that it is allocated on the same memory address.
Also, you need to take care of the return type and parameter list of the functions. The implicit return type is int and empty parameter list means no information is available about the number and type of arguments which means the function takes a fixed but unknown number of arguments of unknown type. You should always explicitly mention void in the parameter list to mean that the function takes no argument.
#include <stdio.h>
// prototype of the function func
void func(void);
// main should have one of the below signatures -
// int main(void); or
// int main(int argc, char *argv[]);
int main(void)
{
func();
func();
func();
}
// explicitly mention void in the
// parameter list to mean the function
// takes no argument
void func(void)
{
// using auto keyword is redundant because
// local variables have automatic storage allocation
int i = 1;
printf("i = %d", i);
i = i + 1;
}
In the second case, you make use of i without ever having initialized it.
The value is therefore undefined by the language. The fact that you see a pattern of the value incrementing is an artifact of the particular compiler you are using.
In the first iteration, you have a random-seeming value that happens to be at the memory location that i represents. Your function increments the value at that memory location, then that memory location happens to be used for subsequent calls.

Resources