为什么此代码会产生意外输出。
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
答案 0 :(得分:11)
当您离开y
时,您正在返回一个指向变量(func
)的指针,该变量超出范围。这是未定义的行为。
目前还不完全清楚你要实现的目标,但有几种方法可以解决这个问题:
int
; *xp
并且不返回任何内容; int*
参数并将结果存储在那里(再次返回void
); malloc
或new
在堆上分配内存并返回(调用者将负责正确释放该内存)。如果不了解更广泛的背景,就无法说出上述哪一项适用于您的问题。
最后,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,它不会为您提供副本。