鱼C论坛

 找回密码
 立即注册
查看: 1582|回复: 2

C语言指针返回值问题

[复制链接]
发表于 2021-2-26 22:54:43 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
#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指向的是谁?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-2-27 08:41:53 From FishC Mobile | 显示全部楼层
确认程序能正确执行??
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-2-27 08:56:43 | 显示全部楼层
这里理论上来说应该是指向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>:  callq  0x555555555050 <printf@plt>   # 调用printf
所以实际上,在0x000055555555516e <+37>:  mov    (%rax),%eax这一行,*p就已经被保存在寄存器中了。而此时还没有执行callq  0x555555555050 <printf@plt>,因此test原来占用的栈帧没有被改变,故p指向的内容还是10。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-14 18:43

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表