You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言返回局部int变量地址与局部字符串地址的差异问题

两个C程序运行差异的底层原因

两个程序的行为差异和返回值是否为局部指针变量无关,核心是返回的指针指向的内存区域的生命周期不同。


第一个程序(返回局部int地址)异常的原因

#include <stdio.h>

int *fun1()
{
    int i = 10;
    return &i;       // 局部变量i,因此在main中无法正常打印取值
}

main()
{
    int *x = fun1();
    printf("%d", *x);
}
  • 这里的变量i是存储在fun1函数栈帧中的自动(auto)变量,它的生命周期完全绑定fun1的执行周期。
  • 当fun1执行结束返回后,它的栈帧会被操作系统回收,这块内存空间会被后续的函数调用(比如后续执行的printf)覆盖重写。
  • 此时返回的&i是指向已回收栈内存的野指针,解引用这个指针属于C语言标准规定的未定义行为,大概率会出现乱码、段错误等异常。

第二个程序(返回局部char*)正常运行的原因

char *fun()
{
    char *p = "ram";
    return p;             // char*是局部变量,即便如此在main中仍能正常打印,原因是什么?
}

int main()
{
    char *x = fun();
    printf("%s", x);
    return 0;
}
  • 这里的p确实是fun函数栈帧上的局部指针变量,但我们返回的是p存储的值,而不是p本身的地址。
  • 代码中的字符串字面量"ram"属于C语言的字符串常量,编译时会被存放在进程地址空间的只读数据段(.rodata段),这个区域的内存生命周期和整个进程的运行周期完全一致,不会因为fun函数栈帧回收而被销毁。
  • 所以p存储的就是这个只读数据段中"ram"的首地址,返回这个地址到main函数中访问是完全合法的,自然可以正常打印。

补充对照验证

如果我们把第二个程序改成如下写法,就会和第一个int的例子一样出现未定义行为:

char *bad_fun()
{
    // 这里arr是栈上的字符数组,会把字符串常量的内容拷贝到栈内存中
    char arr[] = "ram";
    // 返回栈上数组的首地址,属于野指针,访问会异常
    return arr;
}

这个例子完全符合第一个返回局部int地址的错误逻辑,运行会出现异常,进一步验证了核心差异是指针指向的内存区域,而不是指针本身是否为局部变量。

内容的提问来源于stack exchange,提问作者Ravi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 02:06:03