C语言指针返回值问题
#include <stdio.h>int main(){
int a=10,*p;
int *test(int n);
p=test(a);
printf("%d\n",*p);
return 0;
}
int *test(int n){
int *q;
q=&n;
return q;
}
函数执行完之后n不是会被释放么?p指向的是谁? 确认程序能正确执行?? 这里理论上来说应该是指向test函数中行参n的地址。如果编译的时候不启用优化,那么输出的结果应该就是10。
我们认为函数返回后就不应该访问它的局部变量,因为当我们后续调用函数的时候可能会覆盖掉它的值,但是它的局部变量的地址仍然是存在的。要详细了解这一部分内容需要一点内存管理的知识,了解内存中的栈和堆,还有函数调用是在栈上就够了。
而这份代码恰好很幸运,在调用printf函数前,编译器预先将*p的值读入了寄存器中,然后才调用printf函数。
我在ubuntu20.04上用gdb调试了一下,p=test(a)和printf("%d\n",*p)这部分代码汇编代码的执行过程大概是这样的:
在test函数中,n被存储到了地址p = 0x7fffffffde8c,然后test函数返回给p的值是p = 0x7fffffffde8c,p=test(a)执行完毕。这部分内存属于栈内存。
printf("%d\n",*p)的汇编代码如下:
0x000055555555516e <+37>:mov (%rax),%eax # 此时%rax存储的是p,这里将*p传入%eax寄存器
0x0000555555555170 <+39>:mov %eax,%esi # 通常%esi寄存器保存函数的第二个参数
0x0000555555555172 <+41>:lea 0xe8b(%rip),%rdi# 把字符串"%d\n"的地址传入%rdi
0x0000555555555179 <+48>:mov $0x0,%eax # %eax通常存储函数返回值,清零%eax
0x000055555555517e <+53>:callq0x555555555050 <printf@plt> # 调用printf
所以实际上,在0x000055555555516e <+37>:mov (%rax),%eax这一行,*p就已经被保存在寄存器中了。而此时还没有执行callq0x555555555050 <printf@plt>,因此test原来占用的栈帧没有被改变,故p指向的内容还是10。
页:
[1]