局部变量内存分配时间、静态变量的初始化时间、常量折叠

内存分配时间

例1 局部变量

void Test1()
{
    …………
    int buf[1024 * 1024];
    …………
}

在windows下,由于栈限制为1M,上面代码可能会栈溢出,因此通过单步调试我们可以知道,局部变量是在进入函数时分配栈内存。

编译器在编译的过程中,遇到函数调用时,会加入几条汇编指令。这些汇编指令的作用是:
1 分配一段栈空间,用于存放被调函数的参数和局部变量。
2 call被用函数。
3 当被调函数返回时释放掉这段分配栈空间。

例2 全局/静态变量

class B
{
public:
    B(){cout << "class B construct" << endl;}
    ~B(){}
};

class A
{
public:
    A(){cout << "class A construct" << endl;}
    ~A(){}

    static B b;
}

B A::b;

void test()
{
    static A a;
}

int main()
{
    test();
    test();
    return 0;
}

上面代码运行,main函数前,会调用B的构造函数,
test函数中第一次static A a时会调用一次A的构造函数

引用自https://segmentfault.com/q/1010000004157283

  • 对于C语言的全局和静态变量,不管是否被初始化,其内存空间都是全局的;如果初始化,那么初始化发生在任何代码执行之前,属于编译期初始化。由于内置变量无须资源释放操作,仅需要回收内存空间,因此程序结束后全局内存空间被一起回收,不存在变量依赖问题,没有任何代码会再被执行!

  • C++引入了对象,这给全局变量的管理带领新的麻烦。C++的对象必须有构造函数生成,并最终执行析构操作。由于构造和析构并非分配内存那么简单,可以说相当复杂,因此何时执行全局或静态对象(C++)的构造和析构呢?这需要执行相关代码,无法在编译期完成,因此C++标准规定:全局或静态对象当且仅当对象首次用到时才进行构造,并通过atexit()来管理对象的生命期,在程序结束之后(如调用exit,main),按FILO顺序调用相应的析构操作!

  • 总结:
    全局变量、文件域的静态变量和类的静态成员变量在main执行之前的静态初始化过程中分配内存并初始化;局部静态变量(一般为函数内的静态变量)在第一次使用时分配内存并初始化。这里的变量包含内置数据类型和自定义类型的对象。

关于全局/静态变量的内存分配问题,上面总结里已经说的很详细了。
但是我有两点不同看法:

  1. 局部静态变量的内存分配应该和全局变量一样,在main函数之前分配好,在第一次调用的时候只是初始化。
  2. 如果注释掉 B A::b(即不对b进行显式初始化),结果就不会调用B的构造函数。因此对于类的静态成员来说,static B b只是声明,B A::b才是定义,而类中如果是B b则是声明且定义。

例3 常量

引用自https://blog.csdn.net/xiazhiyiyun/article/details/71969618

小结
  1. 对于const全局常量,如果初始值是字面值常量,一般会存放在常量表中,编译器在编译过程中就会直接使用常量表中的值来进行语句的操作。如果经过优化,可能会使得直接使用常而放弃存储在常量表中。
  2. 对于编译器没有办法处理的初始值常量,一般就需要分配到内存空间,然后等待运行时进行赋值,取值时候也是从内存空间中提取。
  3. 对于非static 的 const局部变量(如函数中),由于其是局部变量,符号表中将不存在其值,如果需要内存空间也是在栈中进行分配。根据编译器的优化,以及const 变量初始值的不同来决定是否需要分配内存空间。
  4. 对于static 的 const局部变量(如函数中),会根据编译器的优化能力,以及初始值,来决定其是不进行存储,还是直接存储在常量符号表,或者是栈中等等均有可能。
  5. 对于第三点和第四点可以字迹尝试验证。
<think>好的,我需要解释一下const修饰的变量到底存储在ROM还是RAM里。这个问题看起来和C/C++中的内存分配有关,对吧?首先,我得回忆一下const关键字的作用。const用来声明一个常量,表示这个变量的值在初始化后不能被修改。 那存储位置呢?常见的说法是const变量放在ROM里,但实际情况可能更复杂。我记得不同的平台和编译器可能有不同的处理方式。比如在嵌入式系统中,ROM通常是只读的,所以const变量可能被分配到ROM里,节省RAM空间。但普通的PC程序可能不同,因为它们的ROM可能不可写,但程序运行时需要将数据加载到RAM中。 另外,C/C++标准并没有规定const变量的具体存储位置,这取决于编译器的实现。通常,如果const变量被初始化且是全局的,可能放在只读数据段(比如.rodata),这部分在程序加载时可能被映射到内存的只读区域。而如果是局部const变量,可能还是存储在栈上,也就是RAM里,但编译器会确保其不被修改。 还有,如果const变量的地址被获取,那么它可能需要分配内存空间,这时可能在RAM里。否则,编译器可能会优化为直接替换成常量值,不占用存储空间。所以需要具体情况具体分析,不能一概而论。 总结的话,应该分情况讨论:全局const变量可能存储在ROM或只读段,局部const可能在栈(RAM),而是否取地址也会影响存储位置。不同的编译器和目标平台会有不同的行为,不能简单回答ROM还是RAM。</think>在C/C++中,**const修饰的变量的存储位置取决于具体场景**,不能简单归为ROM或RAM。以下是详细说明: --- ### 1. **全局/静态const变量** - **未取地址时**: 编译器可能直接将其优化为常量折叠(替换成字面值),不占用存储空间。 - **取地址或需要显式存储时**: 通常存储在**只读数据段(.rodata)**。 - **嵌入式系统**:可能映射到ROM(如Flash)。 - **通用系统(如PC)**:加载到内存的只读区域(仍为RAM,但受操作系统保护不可写)。 --- ### 2. **局部const变量** - **未取地址时**: 可能被优化为寄存器变量或直接替换为常量,不占用内存。 - **取地址或需要显式存储时**: 存储在**栈(Stack)**中(属于RAM),但其值在作用域内不可修改。 --- ### 3. **关键影响因素** - **编译器优化**:若未取地址且值可计算,可能被完全优化掉。 - **目标平台特性**: - 嵌入式系统常利用const节省RAM,优先存ROM。 - 通用系统的.rodata段在内存中(RAM),但标记为只读。 - **是否取地址**:取地址会强制分配内存空间。 --- ### 示例分析 ```c const int global_const = 10; // 可能存.rodata(ROM或RAM只读区) void func() { const int local_const = 20; // 可能存栈(RAM)或优化掉 int* ptr = (int*)&local_const; // 强制分配栈空间 } ``` --- ### 总结 - **全局const**:通常存只读段(ROM或RAM的只读区)。 - **局部const**:可能存栈(RAM)或优化消失。 - **核心规则**:C标准不规定存储位置,实际由编译器根据使用场景和平台决定。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值