Does printf function affect the life of variable? - c

This is my simple C program.
#include <stdio.h>
float*multiply(int, float);
main(){
int i =3;
float f = 3.50, *p;
p = multiply(i, f);
printf("%u\n", p);
printf("%f\n", *p);
return 0;
}
float *multiply(int ii, float ff){
float product = ii * ff;
printf("%f\n", product);
printf("%u\n", &product);
return (&product);
}
This program gives the following output:-
But, when I comment out the two "printf" statement in multiply function, It gives the following output:-
I am really sure I'm not doing any silly mistake. I am just commenting out two lines.
Can anyone tell me why is this happening? Is this OS/System related problem?
How is printf function increasing the life of the variable?

You are returning the address of the local, stack-based variable product which will result in undefined behavior.
Also, to print the value of a pointer, you should use %p instead of %u. http://www.cplusplus.com/reference/cstdio/printf/

This is simply an undefined behavior. The lifetime of the variable stays the same - it is limited to the time the function is running. Once the function has exited, all bets are off. Calling printf changes the state of the stack, so the results that you see are different. However, in both cases the results are undefined, meaning that your program can print anything or even crash.
You can detect this undefined behavior by running your program in valgrind.
Note: a proper way to print a pointer is printf("%p\n", (void*)&product);

As mentioned in other answers, by returning the address of product, a local variable, your results are undefined. However, if you return the value of product instead, the result is well defined and your program will work as expected:
#include <stdio.h>
float multiply(int ii, float ff){
float product = ii * ff;
return product;
}
int main(void){
int i =3;
float f = 3.50, p;
p = multiply(i, f);
printf("%p\n", &p);
printf("%f\n", p);
return 0;
}
0x7fff521cfac0
10.500000

If you compile this with the flag -Wall you will see this warning:
test.c:19:4: warning: function returns address of local variable [-Wreturn-local-addr]
This is because you return the memory address of product, and set float p to point to that address, but since that function has finished the memory it used is popped from the stack and no longer guaranteed to be there, meaning p can be pointing to garbage.

After printf() and scanf() sometimes you need to do fflush(stdin) or flushall(). Try that one.

The address of a local variable in a function depends on the state of the stack (the value of the SP register) at the point in execution when the function is called.
In other words, this address is not necessarily the same every time the function is called.
Therefore, returning the address of a local variable leads to undefined behavior.
You can observe the output of the following program as an example:
int func1()
{
int var = 1;
printf("%p\n",&var);
return var;
}
int func2()
{
int var = 2;
func1();
return var;
}
int main()
{
func1(); // main --> func1
func2(); // main --> func2 --> func1
return 0;
}
As implied by #chux in one of the comments below, the C-language standard does not dictate how variables should be allocated in memory. So the problem described above is the result of how most compilers allocate local variables in memory.

Related

while I am trying to play with pointers in c, I faced this problem.where is the output of the program differ form the GDB could someone explain?

I am trying to get deep acknowledge of pointers. while I am running this example it doesn't output any thing due to segmentation fault. But when I am trying to run the code line by line from GDB it works normally
Look at screen shot.
#include <stdio.h>
struct s{
int a;
struct s* next;
};
struct s foo() {
struct s m ;
struct s f[10];
m.a = 55;
m.next =&(f[0]);
int i = 0;
while(i < 9) {
f[i].a = 28 + i;
f[i].next = &(f[i+1]);
i++;
}
return f[0];
}
int main()
{
struct s f = (foo());
printf("%d ",f.a);
printf("%d ",f.next->a);
printf("%d ",f.next->next->a);
return 0;
}
if you change the main function to be like this :
int main(){
struct s f = (foo()); int a = f.a;
int b - f.next->a;
int c = f.next->next->a;
int d = f.next->next->next->a;
int g = f.next->next->next->next->a;
printf("%d %d %d %d %d\n", a, b , c ,d, g);
}
it will work fine.
this screen shot is n't working when I am trying to call printf directly .
this is working when I am trying to store in variables first and then call printf on the variables
]
In C, variables that are defined inside a function are either static or automatic (auto). The default is automatic. The lifetime of automatic variables ends when the function returns and its return value has been copied to another variable or used in an expression.
struct s foo() {
struct s f[10];
int i = 0;
while(i < 9) {
f[i].a = 28 + i;
f[i].next = &(f[i+1]);
i++;
}
return f[0];
}
int main()
{
struct s f = (foo())
So after foo's return value has been stored in main's f, foo's f array is no longer alive, and trying to access any part of it is an error.
So why does the following work?
int b = f.next->a;
int c = f.next->next->a;
int d = f.next->next->next->a;
int g = f.next->next->next->next->a;
printf("%d %d %d %d %d\n", a, b , c ,d, g);
The reason is that your implementation of C stores automatic variables in a stack, and doesn't shrink the stack after a function finishes. Instead, the variables remain undisturbed until another function is called. That function will reuse all or part of the stack space, overwriting variables without regard to their old types. A pointer may be overwritten by an integer, or a few character of a string, or something else.
So, although it's undefined behavior and you should never rely on this working, you can access parts of the f array in this particular case because no function has been called since foo returned.
Similarly, in your GDB session, since you've stopped your program after foo returns but before printf has been called, GDB can safely access f.next->next->a, etc., but it's still undefined behavior.
Your second version does call functions, and that's when you're going to run into trouble.
printf("%d ",f.a);
printf("%d ",f.next->a);
printf("%d ",f.next->next->a);
The first line, printf("%d ",f.a), will work fine. main's f is valid. But the call to printf is going to overwrite the stack previously used by foo, including all or part of what used to be foo's f array.
Note that you won't see this output yet, because printf won't print out anything until you've asked it to print the end-of-line character.
The next line, printf("%d ",f.next->a);, is going to print a seemingly random integer, because foo's f[1].a has been overwritten with whatever local variables printf uses. And, again, you won't see any output yet because of buffering.
The next line, printf("%d ",f.next->next->a), is where things come crashing down. foo's f[1].next is almost certainly not going to be a valid pointer, so you get a segmentation fault.
How can you make this work correctly? If you want foo's f array to stay alive for the entire duration of the program, just prefix the declaration with the keyword static. That means there will be one copy of the f array, no matter how many times you call foo. If you want each call to foo to allocate a new f array, you can use the malloc function. Space allocated by malloc will remain alive until either you call free or the program exits.

Why is this function not pure?

In the Wikipedia article https://en.wikipedia.org/wiki/Pure_function#Impure_functions it says that the following function is not pure.
int f(int* x)
{
return *x;
}
Why is that? The function would return the same value for the same argument right? Would it be considered pure if it was a non-mutable reference, as in the following?
int f2(const int* x)
{
return *x;
}
f isn't pure because its return value isn't necessary the same for the same arguments. You could call f twice with the same inputs and get different outputs. The following program demonstrates this:
#include <stdio.h>
int main() {
int i = 3;
int * const x = &i;
printf("%d\n", f(x));
i = 4;
printf("%d\n", f(x));
return 0;
}
Because x doesn't change between the two calls, the second call to f(x) could be optimized away (in favour of reusing the result from the first call) if f was pure. Obviously, that could produce the wrong result, so f isn't pure.
f2 isn't pure for the same reason.
Rule 1 says:
Its return value is the same for the same arguments (no variation with local static variables, non-local variables, mutable reference arguments or input streams from I/O devices).
The point is that the argument is not the value pointed by x but rather the address of the pointer. You're passing an address to the function.
Since you can change the pointed data and pass the same address then you have different return values.
Of course this wouldn't be true if f or f2 returned int* instead that int. In that case the same argument would lead to the same return value.

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.

Both these simple codes in C are identical but I am getting different outputs. Would love some introspection

Both these simple codes in C are identical but I am getting different outputs. Would love some introspection
The output of first code is correct, it is what i was expecting only i don't understand why output changes by commenting a printf statement, but this is simple only i don't understand the logic even after debugging it, the outputs should be same in both codes as they are same, any help on returning array from functions to main and then printing those arrays would help me.
#include <stdio.h>
int* func ()
{
int a[3] = { 1, 2, 3};
printf ("size: %d\n", sizeof(a[2]));
return a;
}
int main()
{
int *b, c, i;
b = func ();
for (i=0; i<3; i++)
{
printf ("%d\n", *b + i);
}
return 0;
}
Output:
size: 4
1
2
3
#include <stdio.h>
int* func ()
{
int a[3] = { 1, 2, 3};
//printf ("size: %d\n", sizeof(a[2]));
return a;
}
int main()
{
int *b, c, i;
b = func ();
for (i=0; i<3; i++)
{
printf ("%d\n", *b + i);
}
return 0;
}
Output:
1
1962249430
1962249431
This code is exhibiting an undefined behavior. The function func is returning an address of a local variable a, which is going out of scope right after the function returns. Then this address, which is not valid anymore is dereferenced in main causing unexpected stuff happen.
This is very good example of UB.
Which is undefined behavior found in c. Certain codes even though not following rules give correct answers.
But this is a fluke, but not actual answers.
The reason can be anything from "the answers are stored before hand in those address and garbage value is your actual answer" to just "coincidence"
The variable is dereferenced once you come out of loop, try global declaration.
Once func returns, the array a no longer exists, and any pointer to it (such as b) is now invalid. Obviously, the storage that a occupied still exists, but it's now available for other parts of the system to use. So that storage may or may not be overwritten before you try to dereference b.
The behavior upon dereferencing an invalid pointer is undefined - it may do anything from work as expected to crash outright.

simple pointers to pointers

I know why this works:
#include <stdio.h>
void cool_number(int **number) {
int value = 42;
int *p = &value;
*number = p;
}
int main () {
int *number;
cool_number(&number);
printf("number is %d\n", *number);
return 0;
}
What I don't understand is why this doesn't (in my machine it prints 3700 or something like that).
#include <stdio.h>
void cool_number(int **number) {
int value = 42;
int *p = &value;
int **x = &p;
number = x;
}
int main () {
int *number;
cool_number(&number);
printf("number is %d\n", *number);
return 0;
}
Why aren't both equivalent?
both are evil as they capture the address of a stack variable.
Second one doesn't do what you expect because you are assigning directly to the parameter number, which is only temporary, the first one changes something the parameter number pointers to, which is the same thing as number in main points to.
I assume they're not equivalent because number is passed by value, on the stack, as is standard for function parameters. Any changes that you make directly to number inside of cool_number() are modifying the local copy on the stack, and are not reflected in the value of number in main().
You get around this in the first example by dereferencing number, which tells the computer to modify some specific location in memory that you also happen to have a pointer to back in main(). You don't have this in the second example, so all that happens is that you make the local number pointer point to somewhere else, without actually updating any memory location being referred to back in main(). Thus nothing you do shows up once you get back to main().
And since value is local to the cool_number() function, setting a reference to it that will be accessed after cool_number() returns isn't guaranteed to work and certainly shouldn't be used in any code outside of a trivial/toy example. But in this specific instance it's not really related to why you're seeing different results between the two pieces of code.
As I understand, in both cases, your code is wrong.
In the first case, you are returning an address to a variable allocated on stack, which will be deallocated as soon as the function returns.
In the second case, the error of the first case exists, plus you are passing number by value, so an updation to number will not get reflected in the caller function.
In 'C', arguments are always passed by value. So, you cannot update the argument passed as it is. For Ex:
int func(int a)
{
a = 5; // In this case the value 5 will not be reflected in the caller as what is updated is the local copy of a on the stack
}
int func(int *a)
{
*a = 5; // This update will show in caller as you are directly updating the memory pointed to by a
a = malloc(4); //This update will not show in caller as again you are updating the local copy of stack
}
#include <stdio.h>
void cool_number(int **number) {
int value = 42; /* this "value" hold 42 value,
and it lifetime is only in this function */
int *p = &value; /* here we get the address of "value" in memory */
*number = p;
}
int main () {
int *number;
cool_number(&number); /* after this function the "value" in memory had been recyled
and may be used by other program */
printf("number is %d\n", *number); /* so when we print value here it will be
a unpredictable value, somehow may be crash */
return 0;
}
both the same principle

Resources