一、const 常量内存分配时机



在上一篇博客中 , 讲到了获取 const 常量的地址 , 代码如下 :

    // 定义常量
    // 该常量定义在了 符号表 中
    // 符号表 不在内存四区中 , 是另外一种机制
    const int a = 10;

    // 定义一个指针
    int* p = NULL;
    // 将 常量 a 的地址赋值给指针
    // 在 堆内存中重新 分配一个 4 字节的空间 
    // 将 常量 a 的值 10 存储进去
    p = (int *)&a;

在所有的编程语言中 , 常量 都具有如下特点 : 定义时分配内存 , 运行期间保持不变 ;

const 常量 通常指的是在程序运行期间其值不会改变的变量 , 常量在定义后会被分配内存 , 这个过程一般发生在编译器的编译阶段 ;

C++ 程序都是先进行编译 , 然后再执行 , 编译时分配内存意味着在程序运行之前 , 常量在程序内存中的位置就已经固定了 ;

const 常量值在 内存分配完毕后 就不能再被修改 , 因此可以使用常量表示固定值 , 如 : 圆周率 π \pi π , 自然数 e e e ;


const 常量 分配内存的时机 是 编译器 编译期间 进行分配的 ;

指针 p 获取 const 变量地址时 , 会在堆内存中为该指针分配一个内存地址 , 该分配内存的时机 是 编译器 编译 代码期间 进行的 ; ( 不是在运行期间分配内存的 )





二、使用如下代码验证 const 常量内存分配时机



使用如下代码验证 :

// 包含 C++ 头文件
//#include "iostream"

// 使用 std 标准命名空间
//		该命名空间中 , 定义了很多标准定义
//using namespace std;

#include <stdio.h>

int main()
{
    // 定义普通变量
    int a = 0;

    // 定义常量
    // 该常量定义在了 符号表 中
    // 符号表 不在内存四区中 , 是另外一种机制
    const int b = 10;

    // 定义普通变量
    int c = 0;
	
    // 打印上述三个常量/变量 的 地址
    printf("&a = %p , &b = %p , &c = %p\n", &a, &b, &c);

	// 控制台暂停 , 按任意键继续向后执行
	//system("pause");
    return 0;
}

执行结果 :

&a = 00B3F894 , &b = 00B3F888 , &c = 00B3F87C

D:\002_Project\006_Visual_Studio\HelloWorld\HelloWorld\Debug\HelloWorld.exe (进程 21584)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

【C++】C 语言 和 C++ 语言中 const 关键字分析 ② ( const 常量分配内存时机 | const 常量在编译阶段分配内存 )-LMLPHP





三、分析验证结果 - const 常量在编译阶段分配内存



在上述代码中 , 先定义了变量 a , 再定义了常量 b , 最后定义了变量 c ;

变量 a 和 变量 c 肯定是在编译器编译时分配内存的 , 编译器扫描到了变量定义 , 为其分配内存 ;

这里尝试打印 常量 b 的地址 , 执行结果是

&a = 00B3F894 , &b = 00B3F888 , &c = 00B3F87C

三者之间 , 各差 12 字节的内存 , 三个 变量 / 常量 的内存是连续的 , 说明是在同一时间分配的内存 ;

变量 a 和 c 是编译器编译时分配的内存 , 三者内存连续 , 分配内存时间相同 , 说明 常量 b 也是在 编译器编译阶段 分配的内存 ;


这里注意 , 在 Visual Studio 2019 开发环境中 , int 类型本来占 4 字节 , 但是在 Debug 调试模式下 , 前后各分配了 4 字节用于存储调试信息 , 这样占了 12 字节 ;

08-22 12:21