在C中返回地址

时间:2011-09-14 10:31:15

标签: c++ c pointers pass-by-reference

为什么此代码会产生意外输出。

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

预期产出:

10
20

实际输出:

10
1074194112

6 个答案:

答案 0 :(得分:11)

当您离开y时,您正在返回一个指向变量(func)的指针,该变量超出范围。这是未定义的行为。

目前还不完全清楚你要实现的目标,但有几种方法可以解决这个问题:

  1. 按值返回int;
  2. 修改*xp并且不返回任何内容;
  3. 获取额外的int*参数并将结果存储在那里(再次返回void);
  4. 使用mallocnew在堆上分配内存并返回(调用者将负责正确释放该内存)。
  5. 如果不了解更广泛的背景,就无法说出上述哪一项适用于您的问题。

    最后,main() should return int(感谢@pmg发现此事)。这与您遇到的问题无关,但值得指出。

答案 1 :(得分:2)

因为函数返回时y超出范围。记住,y是在堆栈上声明的。这是一种未定义的行为。

答案 2 :(得分:2)

< real_life_example>

想象一下,你把苹果放在桌子上。然后你把它的位置写在一张纸上。 后来有人来接苹果。纸上的位置现在毫无意义。

< / real_life_example>

答案 3 :(得分:1)

返回局部变量的地址,然后对其进行反省略会导致未定义的行为

由于printf调用使用func使用的相同内存(堆栈)区域,因此它们用自己的内部变量和函数参数覆盖func的堆栈帧。

要解决此问题,请使用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;
}

不要忘记free

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

答案 4 :(得分:1)

func应如下所示:

// C++
int* func(int* xp)
{
    int* y = new int;
    *y = 10 + *xp;
    return y;
}

答案 5 :(得分:0)

正如大家已经提到的,您正在尝试返回临时变量的地址。没人提到的是最简单的解决方案。将变量转换为函数内的static。这使得它保留在整个程序的内存中。

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

这可以按预期工作。当然有更好的方法可以解决这个问题,但如果您确实想在函数范围内声明变量并返回它的地址,这是最简单的解决方案。请记住,每次调用此函数时,它都会修改y,它不会为您提供副本。