内存分区与变量作用域全解析

由于内存分区 ,网上各有**叫法混乱,**在这里把易混点做了区分。

程序中变量的作用域生命周期,也做了梳理。

并对**"数组字符串"** 和"指针指向字符串 ",在局部变量返回地址时,为什么有的能返回地址,有的不能返回地址

内存细化

作用域和生命周期

为什么不能返回局部变量的地址

要认知到一点:**字符串字面量本体(也就是 "beoko" 这个双引号包裹的常量):永远存在 .rodata 只读常量区,生命周期为程序全程,**和它写在函数内部还是外部没有任何关系。

char str\[\] 数组:完整存储在栈上,属于局部自动变量;它只是把常量区的字符串内容拷贝了一份副本到栈里,数组本身的位置由它的存储类型决定,和字面量的位置无关。

举例:

1、指针指向字符串地址

cpp 复制代码
char *p = "beoko"

指针 p 本身在栈上(4/8 字节),指针只存地址,不持有字符串内容

指针直接指向 .rodata 里的字面量本体 ,不可通过指针更改.rodata常量,会触发段错误

2、数组复制一份字符串的副本到栈上

cpp 复制代码
char str[] = "beoko"

整个数组(6 字节)都在栈上

数组内容是字面量的栈上副本,可修改数组内容

什么情况下返回字符串地址是安全的?

R 复制代码
char *good_func(void) {
    char *s = "beoko"; 
    // s 本身是栈上的指针变量,但它存的值是常量区字符串的首地址
    return s; 
    // 返回的是「常量区的地址值」,不是栈上数据的地址
}
  • 栈上消失的只是 s 这个指针变量本身(一个存地址的 4/8 字节小变量);
  • 但它保存的地址值,指向的是 .rodata 常量区;常量区是静态存储期,程序全程有效,内容也不会被任何函数覆盖。

一句话区分两种易混淆写法

  • char str[] = "beoko":返回数组名 → 返回栈地址 → 危险
  • char *str = "beoko":返回指针值 → 返回常量区地址 → 安全