区分一些概念
1、变量的值(内容)和变量的地址
2、变量名与地址
变量名的实质
变量名实际上是一个符号地址,在对程序编译连接时由系统给每一个变量名分配一个内存地址。在程序中从变量中取值,实际上是通过变量名找到相应的内存地址,从其存储单元中读取数据。
变量名(Variable Name): 编译器的 符号表(Symbol Table) 中的一个条目,包含名称、类型、作用域、地址等信息。
- 关键细节:
- 名称修饰(Name Mangling):C++ 中为支持重载,编译器会修改函数/变量名(如
_Z3fooi
)。 - 作用域解析:编译器通过符号表区分局部变量与全局变量(如
::a
vsa
)。 - 调试符号:编译时若保留调试信息(如
-g
选项),变量名会被嵌入二进制文件供调试器使用。
- 名称修饰(Name Mangling):C++ 中为支持重载,编译器会修改函数/变量名(如
地址(Address): 一个无符号整数,通常为 CPU 字长,
- 关键细节:
- 虚拟地址:程序看到的是操作系统提供的虚拟地址,由 MMU(内存管理单元)转换为物理地址。
- 地址空间布局随机化(ASLR):现代系统随机化进程地址空间以提高安全性。
- 空指针(NULL):通常定义为
(void*)0
,访问它会导致段错误(Segmentation Fault)。
3、指针
指针变量
指针也是变量,存储的是地址,指向该地址
c
int a = 112, b = -1;
float c = 3.14;
int *d = &a;
float *e = &c;
地址 | 100 | 104 | 108 | 112 | 116 |
---|---|---|---|---|---|
变量名 | a | b | c | d | e |
值 | 112 | -1 | 3.14 | 100 | 108 |
间接访问
通过一个指针访问他所指向的地址的过程称为间接访问或解引用指针: 使用单目操作符 *
c
int f = *d;
未初始化和非法的指针
一个极为常见的错误:
c
int *a;
...
*a = 12;
无法预测 12 会存储在哪个地方, 声明一个指向整型的指针不会“创建”用于储存整型的内存空间。 一般情况,会指向一个非法地址: 在UNIX上会导致“内存错误”(memory fault) 在Windows上会导致“保护性异常”(general protection exception) 最严重的情况,可能指向了一个合法的地址: 位于那个位置的值被修改,这种错误难以捕捉,导致严重后果。