2

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:-

enter image description here

But, when I comment out the two "printf" statement in multiply function, It gives the following output:-

enter image description here

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?

Anish Shah
  • 7,669
  • 8
  • 29
  • 40
  • 10
    Undefined behaviour is undefined. Dereferencing a dangling pointer is undefined behaviour. So is printing a pointer with `%u`. That should be `%p` and `(void *)p`. – chris Aug 12 '14 at 15:51
  • 5
    Never return a pointer to a local... – StoryTeller - Unslander Monica Aug 12 '14 at 15:52
  • If you want to work on the same memory area out and inside the function, you should pass it to function as a reference. Like void/bool multiply(int ii, float ff, float &result); – Sebastian Xawery Wiśniowiecki Aug 12 '14 at 18:04
  • you can also `malloc()` the float pointer and then store the result of the calculation in there. don't forget to `free()` in main –  Aug 12 '14 at 19:53
  • possible duplicate of [Can a local variable's memory be accessed outside its scope?](http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope) – Raymond Chen Aug 13 '14 at 07:55

6 Answers6

2

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/

edtheprogrammerguy
  • 5,957
  • 6
  • 28
  • 47
2

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);

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

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

Fiddling Bits
  • 8,712
  • 3
  • 28
  • 46
0

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.

barak manos
  • 29,648
  • 10
  • 62
  • 114
  • Note: Some architectures exists so that "address of a local variable in a function depends on the state of the stack" is not true. That is: the "address of a local variable in a function is fixed". Still, per C, OP's code is UB. – chux - Reinstate Monica Aug 12 '14 at 19:48
  • @chux: I agree on the fact that the C-language standard does not define the way in which variables should be allocated in memory. Yet, it feels a bit awkward to give a "presumably" practical and constructive answer, that says nothing more than - "it's undefined behavior by the standard". Why is it undefined behavior? Well, because how compilers implement the standard. Does the standard say anything about how compilers should implement it? No... I hope you get my point at this point :) I've seen plenty of "UB" answers on this web-site, that simply fail to "serve the purpose"... – barak manos Aug 12 '14 at 20:02
0

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.

James
  • 3,957
  • 4
  • 37
  • 82
0

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