1

Why this code is giving unexpected output.

int * func(int *xp)
{
    int y = 10 + *xp;
    return (&y);
}
void main()
{
    int x = 10;
    int *xp = func(&x);
    printf("%d\n", x);
    printf("%d\n", *xp);
}

expected output:

10
20

Real Output:

10
1074194112
phihag
  • 278,196
  • 72
  • 453
  • 469
Kuntal Basu
  • 830
  • 2
  • 12
  • 28
  • 4
    `void main` **ARRRRRRRRGGGGGGGGHHHHHHHH!** – pmg Sep 14 '11 at 10:38
  • Kind of a FAQ. See [Eric Lippert's explanation](http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope/6445794#6445794). 1851 upvotes and counting... – Eran Sep 14 '11 at 10:44
  • 1
    @pmg whats the problem with void main??? When compiler doesn't give any error for that then why do you worrie??? – Kuntal Basu Sep 14 '11 at 10:49
  • 2
    @Kuntal: the problem is that you are unnecessarily limiting your program to be compilable (and to run) only on implementations that accept that. By using the Standard definition (`int main(void)` or `int main(int argc, char **argv)` or some other C++ option) you guarantee that line of your program is compilable everywhere – pmg Sep 14 '11 at 11:00
  • @pmg hmmmm I got it. Thanks pmg. – Kuntal Basu Sep 14 '11 at 11:08
  • 1
    @pmg: The standard does not allow an implementation to accept `void main` unless it's a freestanding (non-hosted) implementation. Custom argument number/types are allowed as an implementation extension, but different return types are not. As such, `void main` is **invalid C** for a hosted implementation, period. – R.. GitHub STOP HELPING ICE Sep 14 '11 at 12:30
  • possible duplicate of [Returning the address of local or temporary variable](http://stackoverflow.com/questions/2744264/returning-the-address-of-local-or-temporary-variable) – pmr Sep 14 '11 at 12:42
  • @R..: I read the Standard differently. Specifically 5.1.2.2.3/1 (in n1256.pdf) says "... If the return type [of the `main` function] is not compatible with `int`, the termination status returned to the host environment is unspecified." which makes me believe the intention was to allow implementations to accept different return types (which, of course, renders the code non strictly-conformant). – pmg Sep 14 '11 at 13:38

6 Answers6

10

You are returning a pointer to a variable (y) that goes out of scope the moment you leave func. This is undefined behaviour.

It is not entirely clear what you're trying to achieve, but there are several ways to fix this:

  1. return the int by value;
  2. modify *xp in place and don't return anything;
  3. take an additional int* parameter and store the result in there (again returning void);
  4. allocate memory on the heap using malloc or new and return that (the caller would be responsible for correctly freeing that memory).

It is impossible to say which of the above are applicable to your problem without knowing the broader context.

Lastly, main() should return int (thanks @pmg for spotting this). This is not related to the problem you're having but is worthing pointing out.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
2

Because y goes out of scope when function returns. Remember, y was declared on the stack. This is an undefined behavior.

Aamir
  • 14,882
  • 6
  • 45
  • 69
2

< real_life_example >

Imagine you put an apple on the table. You then write down it's position on a piece of paper. Later, someone comes and takes the apple. The position on the piece of paper now makes no sense.

< /real_life_example >

wormsparty
  • 2,481
  • 19
  • 31
1

Returning the address of a local variable and then derefencing it causes undefined behavior.

Since the printf calls use the same memory (stack) region that func uses, they overwrite the stack frame of func with their own internal variables and function arguments.

To solve this problem, allocate memory on the heap with malloc:

int* func (int *xp) {
  int* res = malloc(sizeof(int));
  if (!res) {
    perror('Cannot allocate memory in func');
    exit(1);
  }
  *res = 10 + *xp;
  return res;
}

Don't forget to free it:

int main(void) {
    int x = 10;
    int *xp = func(&x);
    printf("%d\n", x);
    printf("%d\n", *xp);
    free(xp);
    return 0;
}
pmg
  • 106,608
  • 13
  • 126
  • 198
phihag
  • 278,196
  • 72
  • 453
  • 469
1

func should look like this:

// C++
int* func(int* xp)
{
    int* y = new int;
    *y = 10 + *xp;
    return y;
}
npclaudiu
  • 2,401
  • 1
  • 18
  • 19
0

As everyone mentioned already, you are trying to return the address of a temporary variable. What nobody has mentioned is the easiest solution. Cast the variable as static inside the function. This makes it remain in memory for the entirety of the program.

int * func(int *xp)
{
    static int y;
    y = 10 + *xp;
    return (&y);
}
void main()
{
    int x = 10;
    int *xp = func(&x);
    printf("%d\n", x);
    printf("%d\n", *xp);
}

This works as expected. Of course there are better ways to go about this, but this is the simplest solution if you indeed want to declare a variable inside the scope of a function, and return it's address. Keep in mind, every time this function is called, it modifies y, it doesn't give you a copy.

William
  • 91
  • 2