文章目录
- 一、const 常量内存分配时机
- 二、使用如下代码验证 const 常量内存分配时机
- 三、分析验证结果 - const 常量在编译阶段分配内存
一、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 = 00B3F87CD:\002_Project\006_Visual_Studio\HelloWorld\HelloWorld\Debug\HelloWorld.exe (进程 21584)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
三、分析验证结果 - 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 字节 ;