preserved value of a variable in C - c

#include <stdio.h>
#include <stdlib.h>
void func(int i);
int main() {
int i;
for(i=0;i<3;i++){
func(i);
}
return 0;
}
void func(int i){
int k;
if(i==0){
k=4;
}
printf("%d\n",k);
Sample Run:
4
4
4
Can someone please explain how come k is always equal to 4. Everytime I call the function I am redefining k and how can the value of k be preserved everytime I call the function

You're not initializing k either... so it's probably just re-using the same memory location each time you call the function and it just happens to still be 4 from the first call...
Try this int k = 0;

If you want to preserve the value of K but into the local scope of the function you could use the static type modificator.
static int k=0;
thus, your variable is global from the point of view of duration, but its scope is local to the function or block where it is initialized.
And yes,.. probably the function reuses the same location of k, because you do not initialize its value as Buddy points out.

Your current code exhibits undefined bahaviour (there might be demons flying out of your nose), as k is not initialized. Any value you actually read is invalid (technically: whatever is at its current memory location). Rason is that local variables are not initialized by default for performance reasons.
So, if you do not want that, you have to explictily initialize it by an initial assignment. This may be included in the definition as for any other variable, but with a non-constant expression.
If you want to keep the last value of k, you have to define it static. Note that any initialization is done when the program loads and it does preserve its value between calls. Thus, the initialization has to be a constant expression If you do not explicitly initialize it, it defaults to 0.

Related

Malloc altering behavior of uninitialized variable in separate function?

This is a question for my Programming Langs Concepts/Implementation class. Given the following C code snippet:
void foo()
{
int i;
printf("%d ", i++);
}
void main()
{
int j;
for (j = 1; j <= 10; j++)
foo();
}
The local variable i in foo is never initialized but behaves similarly to a static variable on most systems. Meaning the program will print 0 1 2 3 4 5 6 7 8 9. I understand why it does this (the memory location of i never changes) but the question in the homework asks to modify the code (without changing foo) to alter this behavior. I've come up with a solution that works and makes the program print ten 0's but I don't know if it's the "right" solution and to be honest I don't exactly know why it works.
Here is my solution:
void main()
{
int j;
void* some_ptr = NULL;
for (j = 1; j <= 10; j++)
{
some_ptr = malloc(sizeof(void*));
foo();
free(some_ptr);
}
}
My original thought process was that i wasn't changing locations because there was no other memory manipulation happening around the calls of foo, so allocating a variable should disrupt that, but ince some_ptr is allocated in the heap and i is on the stack, shouldn't the allocation of some_ptr have no effect on i? My thought is that the compiler is playing some games with the optimization of that subroutine call, could anyone clarify?
There cannot be a "right" solution. But there can be a class of solutions which work for a particular CPU architecture, ABI, compiler, and compiler options.
Changing the code to something like this will have the effect of altering the memory above the stack in a way which should affect many, if not most, environments in the targeted way.
void foo()
{
int i;
printf("%d ", i++);
}
void main()
{
int j;
int a [2];
for (j = 1; j <= 10; j++)
{
foo();
a [-5] = j * 100;
}
}
Output (gcc x64 on Linux):
0 100 200 300 400 500 600 700 800 900
a[-5] is the number of words of stack used for overhead and variables spanning the two functions. There is the return address, saved stack link value, etc. The stack likely looks like this when foo() writes to a[-5]:
i
saved stack link
return address
main's j
(must be something else)
main's a[]
I guessed -5 on the second try. -4 was my first guess.
When you call foo() from main(), the (uninitialized) variable i is allocated at a memory address. In the original code, it so happens that it is zero (on your machine, with your compiler, and your chosen compilation options, your environment settings, and given the current phase of the moon — it might change when any of these, or a myriad other factors, changes).
By calling another function before calling foo(), you allow the other function to overwrite the memory location that foo() will use for i with a different value. It isn't guaranteed to change; you could, by bad luck, replace the zero with another zero.
You could perhaps use another function:
static void bar(void)
{
int j;
for (j = 10; j < 20; j++)
printf("%d\n", j);
}
and calling that before calling foo() will change the value in i. Calling malloc() changes things too. Calling pretty much any function will probably change it.
However, it must be (re)emphasized that the original code is laden with undefined behaviour, and calling other functions doesn't make it any less undefined. Anything can happen and it is valid.
The variable i in foo is simply uninitialized, and uninitialized value have indeterminate value upon entering the block. The way you saw it print certain value is entirely by coincident, and to write standard conforming C, you should never rely on such behavior. You should always initialize automatic variables before using it.
From c11std 6.2.4p6:
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.
The reason the uninitialized value seems to keep its value from past calls is that it is on the stack and the stack pointer happens to have the same value every time the function is called.
The reason your code might be changing the value is that you started calling other functions: malloc and free. Their internal stack variables are using the same location as i in foo().
As for optimization, small programs like this are in danger of disappearing entirely. GCC or Clang might decide that since using an uninitialized variable is undefined behavior, the compiler is within its rights to completely remove the code. Or it might put i in a register set to zero. Then decide all printf calls output zero. Then decide that your entire program is simply a single puts("0000000000") call.

Scope and lifetime of local variables in C

I would like to understand the difference between the following two C programs.
First program:
void main()
{
int *a;
{
int b = 10;
a=&b;
}
printf("%d\n", *a);
}
Second program:
void main()
{
int *a;
a = foo();
printf("%d\n", *a);
}
int* foo()
{
int b = 10;
return &b;
}
In both cases, the address of a local variable (b) is returned to and assigned to a. I know that the memory a is pointing should not be accessed when b goes out of scope. However, when compiling the above two programs, I receive the following warning for the second program only:
warning C4172: returning address of local variable or temporary
Why do I not get a similar warning for the first program?
As you already know that b goes out of scope in each instance, and accessing that memory is illegal, I am only dumping my thoughts on why only one case throws the warning and other doesn't.
In the second case, you're returning the address of a variable stored on Stack memory. Thus, the compiler detects the issue and warns you about it.
The first case, however skips the compiler checking because the compiler sees that a valid initialized address is assigned to a. The compilers depends in many cases on the intellect of the coder.
Similar examples for depicting your first case could be,
char temp[3] ;
strcpy( temp, "abc" ) ;
The compiler sees that the temp have a memory space but it depends on the coder intellect on how many chars, they are going to copy in that memory region.
your foo() function has undefined behavior since it returns a pointer to a part of stack memory that is not used anymore and that will be overwritten soon on next function call or something
it is called "b is gone out of scope".
Sure the memory still exists and probably have not changed so far but this is not guaranteed.
The same applies to your first code since also the scope of b ends with the closing bracket of the block there b is declared.
Edit:
you did not get the warning in first code because you did not return anything. The warning explicitly refers to return. And since the compiler may allocate the stack space of the complete function at once and including all sub-blocks it may guarantee that the value will not be overwritten. but nevertheless it is undefined behavior.
may be you get additional warnings if you use a higher warning level.
In the first code snippet even though you explicitly add brackets the stack space you are using is in the same region; there are no jumps or returns in the code so the code still uses consecutive memory addresses from the stack. Several things happen:
The compiler will not push additional variables on the stack even if you take out the code block.
You are only restricting the visibility of variable b to that code-block; which is more or less the same as if you would declare it at the beginning and only use it once in the exact same place, but without the { ... }
The value for b is most likely saved in a register which so there would be no problem to print it later - but this is speculative.
For the second code snippet, the function call means a jump and a return which means:
pushing the current stack pointer and the context on the stack
push the relevant values for the function call on the stack
jump to the function code
execute the function code
restore the stack pointer to it's value before the function call
Because the stack pointer has been restored, anything that is on the stack is not lost (yet) but any operations on the stack will be likely to override those values.
I think it is easy to see why you get the warning in only one case and what the expected behavior can be...
Maybe it is related with the implementation of a compiler. In the second program,the compiler can identify that return call is a warning because the program return a variable out of scope. I think it is easy to identify using information about ebp register. But in the first program our compiler needs to do more work for achieving it.
Your both programs invoke undefined behaviour. Statements grouped together within curly braces is called a block or a compound statement. Any variable defined in a block has scope in that block only. Once you go out of the block scope, that variable ceases to exist and it is illegal to access it.
int main(void) {
int *a;
{ // block scope starts
int b = 10; // b exists in this block only
a = &b;
} // block scope ends
// *a dereferences memory which is no longer in scope
// this invokes undefined behaviour
printf("%d\n", *a);
}
Likewise, the automatic variables defined in a function have function scope. Once the function returns, the variables which are allocated on the stack are no longer accessible. That explains the warning you get for your second program. If you want to return a variable from a function, then you should allocate it dynamically.
int main(void) {
int *a;
a = foo();
printf("%d\n", *a);
}
int *foo(void) {
int b = 10; // local variable
// returning the address of b which no longer exists
// after the function foo returns
return &b;
}
Also, the signature of main should be one of the following -
int main(void);
int main(int argc, char *argv[]);
In your first program-
The variable b is a block level variable and the visibility is inside that block
only.
But the lifetime of b is lifetime of the function so it lives upto the exit of main function.
Since the b is still allocated space, *a prints the value stored in b ,since a points b.

static keyword on a function call

About the following code:
#include <stdio.h>
int lastval(void)
{
`static int k = 0;
return k++;
}
int main(void)
{
int i = 0;
printf("I previously said %d\n", lastval());
i++;
i++;
i++;
i++;
i++;
printf("I previously said %d\n", lastval());
i++;
i++;
i++;
printf("I previously said %d\n", lastval());
i++;
i++;
i++;
printf("I previously said %d", lastval());
i++;
i++;
i++;
return 0;
}
can anyone explain to me how does static maintain its value ? I though it was because the stack frame for the function wasnt destroyed after the return so I wrote this code to run it under gdb and I after doing backtraces after every single line only main's stack frame show up (it doesnt even list lastval when I do a backtrace sitting on a printf call, but anyway).
How its k actually stored ? I know that's not like a normal variable since the first k++ returns 1 instead of 0, and its not like a global since i cant access k inside main for example, so .. what's going on ?
`on a local k, K++ // Always returns 0
`on a global k = 0, k++ // returns 0, 1, 2
`on a static k, k++ // returns 1, 2 ,3
Can anyone help me to understand these 2 issues ?
A static definition inside a function is just like a static definition outside a function other than the scope of the symbol (where in your the program you can refer to it). It has nothing to do with stack frames ... k isn't on the stack, it's in "static"/global/.data memory.
I know that's not like a normal variable since the first k++ returns 1 instead of 0
No, it returns 0, but k's value is then 1.
on a static k, k++ // returns 1, 2 ,3
No, that's not correct ... it returns 0, 1, 2 ...
and its not like a global since i cant access k inside main for example
That's simply how name scopes work; it has nothing to do with how k is stored.
variable k is defined inside function lastval so its scope is in this function only.But since you defined it with static keyword, its lifetime becomes equal to lifetime of programme.
so as per definition of static this variable k will be initialized only once and it will retain its last value and that is what happening in your case.Initialized static variable will go in .data section of memory.so k will get memory in .data.
The static variables stored as globals, except their scope. Your program outputs 0 1 2 3 on my computer, so double-check it.
Not to be snarky, but any reference on C will explain this.
The static keyword used on a variable within a function allows the value to persist across function calls. It's stored like a global, but you can only access it by name within the scope of the function where it is defined.
Some typical uses of static variables in the standard C library occur in the implementations of rand(3) and strtok(3). Their use is commonly discouraged because it can lead to functions that are not reentrant and thus play havoc when multiple threads are used. POSIX defines a strtok_r function for use when reentrancy is required.
The static variables are instantiated in the global memory space (Not in a stack frame) before the program start executing the main.
C,
That variable is initialized before the program start executing the main.
C++,
That variable is initialized when the program encounters this line for the 1st time.
When you execute the "lastval()" function, that "static int k = 0" will not be executed again.

Does local variable be deleted from memory when this function is called in main [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Can a local variable's memory be accessed outside its scope?
returning address of local variable
I have a question, first of all look at the code
#include <stdio.h>
int sum(); /* function declaration */
int main()
{
int *p2;
p2 = sum(); /* Calling function sum and coping its return type to pointer variable p2 */
printf("%d",*p2);
} /* END of main */ `
int sum()
{
int a = 10;
int *p = &a;
return p;
} /* END of sum */
I think the answer is 10 and address of variable a, but my tesacher says that a is local to the function come so a and its
value will be deleted from the memory location when the function returns or is finished executing. I tried this code and the answer is weel of course 10 and address of a, I use the GNU/GCC compiler. Can anyone say what is right and wrong.
Thanks in advance.
Your teacher is absolutely right: even if you fix your program to return int* in place of int, your program still contains undefined behavior. The issue is that the memory in which a used to be placed is ripe for reuse once sum returns. The memory may stay around untouched for you to access, so you might even print ten, but this behavior is still undefined: it may run on one platform and crash on ten others.
You may get the right result but that is just because you are lucky, by the time the sum() is returned, the memory of a is returned to the system, and it can be used by any other variables, so the value may be changed.
For example:
#include <stdio.h>
int* sum(); /* function declaration */
int* sum2(); /* function declaration */
int main()
{
int *p2;
p2 = sum(); /* Calling function sum and coping its return type to pointer variable p2 */
sum2();
printf("%d",*p2);
}
int* sum()
{
int a = 10;
int *p = &a;
return p;
} /* END of sum */
int* sum2()
{
int a = 100;
int *p = &a;
return p;
} /* END of sum */
With this code, the a will be reused by sum2() thus override the memory value with 100.
Here you just return a pointer to int, suppose you are returning an object:
TestClass* sum()
{
TestClass tc;
TestClass *p = &tc;
return p;
}
Then when you dereference tc, weird things would happen because the memory it points to might be totally screwed.
Your pointer still points to a place in memory where your 10 resides. However, from Cs point of view that memory is unallocated and could be reused. Placing more items on the stack, or allocating memory could cause that part of memory to be reused.
The object a in the function sum has automatic lifetime. It's lifetime will be ended as soon as the scope in which it has been declared in (the function body) is left by the program flow (the return statement at the end of the function).
After that, accessing the memory at which a lived will either do what you expect, summon dragons or set your computer on fire. This is called undefined behavior in C. The C standard itself, however, says nothing about deleting something from memory as it has no concept of memory.
Logically speaking, a no longer exists once sum exits; its lifetime is limited to the scope of the function. Physically speaking, the memory that a occupied is still there and still contains the bit pattern for the value 10, but that memory is now available for something else to use, and may be overwritten before you can use it in main. Your output may be 10, or it may be garbage.
Attempting to access the value of a variable outside that variable's lifetime leads to undefined behavior, meaning the compiler is free to handle the situation any way it wants to. It doesn't have to warn you that you're doing anything hinky, it doesn't have to work the way you expect it to, it doesn't have to work at all.

Passing arrays, pointers to int in C

I'm new to C for numerical analysis after many years of working with Matlab. I have a function that constructs an array and I need to get it back to main(). I had the usual trouble with arrays vs. pointers, and by fiddling figured out how to do this. But the fiddling left me with a conceptual question based on the following code.
#include <stdio.h>
void array_set(int y_out[2][2]);
void int_set_wrong(int y);
void int_set_right(int *y);
int main (int argc, const char * argv[]) {
int y_array[2][2]={{0,0},{0,0}};
int y_int_1 = 0;
int y_int_2 = 0;
array_set(y_array);
int_set_wrong( y_int_1 );
int_set_right( &y_int_2 );
printf("\nValue array: %d \n",y_array[0][0]);
printf("Value int wrong: %d \n",y_int_1);
printf("Value int right: %d \n",y_int_2);
return 0;
}
void array_set(int y_out[2][2]){
y_out[0][0] = 10;
y_out[1][0] = 20;
y_out[0][1] = 1;
y_out[1][1] = 2;
}
void int_set_wrong(int y){
y = 10;
}
void int_set_right(int * y){
*y = 10;
}
The snippet above returns:
Value array: 10
Value int wrong: 0
Value int right: 10
My question is in a few parts,
first, why does the function 'array_set' work? I would expect it to fail in the same way that 'int_set_wrong' did.
How are ints and int arrays treated differently in passing?
Furthermore, in the case of 'int_set_wrong', is there a local version of y?
If so, why is there not a local version of y_out in case of setting the array?
Thanks for the help. As an aside, if there is anything that will cause problems with my implementation of array_set, please chime in.
--Andrew
In int_set_right() you passed the address of the variable y_int_2 (which you declared and defined in main()) through the operator &.
int_set_right( &y_int_2 );
Since the function had access to the actual variable y_int_2 through the pointer y (set to the value of the address of y_int_2 from &y_int_2), you assigned y_int_2 the value 10 when you assigned *y = 10.
You can read *y = 10 as:
the value of the variable whose
address is stored in y is now set to
10
But for y_int_1, you merely passed the value. So a temporary variable was created when you called int_set_wrong() which was initialized with the value of y_int_1. So all you did was change the value of the temporary of the local variable (local to int_set_wrong()).
This is why the y_int_1 declared in main() is not affected by int_set_wrong().
array_set works because you passed the address of y_array to the function through the y_out variable (which is a pointer like y in int_set_right).
Arrays are passed using pointers rather than the entire array being copied by value on the stack. Your two dimensional array makes explaining this tricky, but consider a one dimensional version:
void f(int x[]){
x[0] = 1;
x[1] = 2;
}
You could equivalently write this as:
void f(int *x){
x[0] = 1;
x[1] = 2;
}
These two declarations are identical, but I'm sure you can see that modifications made in the the second version are propagated back to the caller.
The function array_set works because when you pass an array into a function, you are really passing a pointer. Then, inside the function, you are de-referencing the array using "y_out[0][0] = 10" etc. When you use array notation, it automatically de-references the array pointer so you are able to set the values within the array.
Ints are completely different from int arrays. An array can be treated in almost every case as a pointer, in this case a pointer to int. An int is an actual numerical value. Therefore, when you pass an int into you're int_set_wrong function, it is copied (that's just what C/C++ does), and you are setting a local variable y, not the int you passed in.
You're third question is answered in the first paragraph as well. Hope this clears things up.
Your function works because in C the inner most [] in function arguments (and only there!) is equivalent to a pointer argument. Your declaration is equivalent to
void array_set(int (*y_out)[2]){
..
}
That is y_out is a pointer to int[2].
You've created 3 functions.
array_set(y_array);
Prior to this you have created an array of numbers with the line.
int y_array[2][2]={{0,0},{0,0}};
In C when you declare an array you created a pointer in your code with the name y_array the array is stored somewhere in the memory and the pointer is pointing is holding the position of the location.
So essentially its a normal pointer with a big amount of memory allocated after it.
When you pass the array to save memory and time C by default passes the pointer.
void int_set_wrong(int y);
When you pass an int it copies the value to a local variable as a result, you don't hold any address to that variable outside that function.
When you pass the reference of an int you supply the function with the address of your int variable. As a result, the function can make changes there.
As the first and third call is sharing the location of the main variable you can see the change from the main. For the second one there is no sharing of address. So the function creates its own variable which cannot be accessed from outside.

Resources