以下代码的输出为2500.它包含指针。有人可以给出正确的解释吗?为什么打印为2500?是通过指针声明还是有另一个原因?
#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;
}
答案 0 :(得分:8)
您获得奇怪输出的原因是未定义的行为。您将返回自动局部变量的地址,该函数在函数到达时将不再存在。
虽然,可以根据函数调用的堆栈帧给出输出的说明。由于最后一次调用是函数g
,并且传递给它的参数是2500
,因此函数x
的参数g
在堆栈上分配,而2500
是推到了堆栈。当此函数返回时,此值从堆栈中弹出(尽管返回到调用者后g
的堆栈帧无效)并且它可能从其堆栈帧返回此2500
。
答案 1 :(得分:5)
在这两个函数中,您尝试在函数中返回 local 变量的地址。一旦函数完成执行并且控件返回给调用者,返回的地址就变为无效(即,变量超出范围),并且任何使用返回值的尝试都会调用undefined behavior。
如果你必须从函数返回一个地址并在调用者中使用它,你将需要一个通过动态内存分配器函数分配内存的指针,如malloc()
和family。
答案 2 :(得分:2)
我认为可以使用堆栈来解释所发生的事情。调用函数f时,堆栈的行为如下。 “ret”是返回地址。
2| | 2| | 2| | 2| p |
1| | -> 1| | -> 1|ret| -> 1|ret|
0| | 0|100| 0|100| 0|100|
现在堆栈指针位于2,并返回该地址(p的地址)并将其分配给main中的* x。当它从f返回时,会弹出所有堆栈值,但实际发生的情况只是减少堆栈指针的值。因此推出的价值仍然存在。 再次调用函数g,堆栈如下。
2| p | 2| p | 2| p | 2| y |
1|ret | -> 1|ret | -> 1|ret | -> 1|ret |
0|100 | 0|2500| 0|2500| 0|2500|
与函数f相同,返回p的地址并在main中分配给* y。但请注意,它也是与p,2相同的地址。因此,* x和* y在main中都指向相同的位置。函数g将该地址的值设置为2500,因此* x和* y都打印2500。
希望这会有所帮助。 :)