Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

would that be wrong? And if so why is it? The output is 2500

The output of the below code is 2500. It contains pointers. Can someone give a proper explanation of this? Why does it print as 2500? Does it come through the pointer declaration or is there another reason?

#include <stdio.h>

/* Two functions include and they are operated by main function */

int *f(int x) {
    /* Creates an variable */
    int p;
    p = x;
    return &p;
}

/* Here the initialization of the function g */
int *g(int x) {
    /* Creates an variable */
    int y;
    y = x;
    return &y;
}

/* This creates two pointers called x and y */
int main() {
    int *x, *y;
    /* Here call the functions f and g */
    x = f(100);
    /* Here call the function g */
    y = g(2500);
    /* How does it print 2500? */
    /* print the value of x */
    printf("%d \n", *x);
    return 0;
}
like image 325
Thilina Viraj Avatar asked Dec 26 '15 16:12

Thilina Viraj


3 Answers

The reason you are getting weird output is undefined behavior. You are returning the address of automatic local variable which will no longer exist once function reach its end.

Although, the explanation for the output can be given in terms of stack frame of function call. Since the last call is for function g and the argument passed to it is 2500, the parameter x of function g is allocated on stack and 2500 is pushed to the stack. When this function return, this value popped from the stack (though the stack frame for g is invalid after return to the caller) and it may return this 2500 from its stack frame.

like image 57
haccks Avatar answered Nov 14 '22 18:11

haccks


In both of your functions, you try to return the address of a local variable in the function. Once the function finishes the execution and the control returns to the caller, the returned address becomes invalid (i.e., the variables go out of scope) and any attempt to make use of the returned value invokes undefined behavior.

If you have to return an address from a function and use it in the caller, you'll be needing a pointer which has been allocated memory through dynamic memory allocator functions, like malloc() and family.

like image 23
Sourav Ghosh Avatar answered Nov 14 '22 18:11

Sourav Ghosh


I think what happens can be explained using the stack. When calling the function f, stack behaves as follows. "ret" is the return address.

2|   |    2|   |    2|   |    2| p |   
1|   | -> 1|   | -> 1|ret| -> 1|ret|
0|   |    0|100|    0|100|    0|100|

Now stack pointer is at 2, and that address (address of p) is returned and assigned to *x in main. When it returns from f, all stack values are popped, but actually what happens is just reducing the value of the stack pointer. Therefor the values pushed are still there. The again function g is called and stack is as follows.

2| p  |    2| p  |    2| p  |    2| y  |
1|ret | -> 1|ret | -> 1|ret | -> 1|ret |
0|100 |    0|2500|    0|2500|    0|2500|

Same as function f, address of p is returned and assigned to *y in main. But notice that it's also the same address as p, 2. Hence *x and *y in main both point to the same location. Function g set the values of that address to 2500, so both *x and *y prints 2500.

Hope this helps. :)

like image 2
Vihanga Liyanage Avatar answered Nov 14 '22 16:11

Vihanga Liyanage