C++数组内存分配地址选择及指针赋值后地址异常咨询
你的两个C++内存疑惑解答
一、数组地址间隔16字节不是防越界措施,是内存对齐与栈布局规则导致的
首先得明确:编译器给栈上变量分配地址时,核心考虑的是内存对齐(Memory Alignment)和栈帧的布局优化,不是为了防止数组越界。
你看到的两个数组地址相差16字节,大概率是这几个原因:
- 内存对齐要求:现代CPU访问内存时,对于int这类基础数据类型,通常要求地址是其大小的整数倍(比如int是4字节,地址要能被4整除;部分平台的double则要求8字节对齐)。编译器会在变量之间自动填充空白字节(padding),保证每个变量都满足对齐要求。
- 栈的增长方向:多数平台的栈是从高地址向低地址增长的,后定义的变量地址会比先定义的更低。如果你的两个数组大小加上必要的padding刚好凑成16字节的间隔,就会出现这种情况。
- 栈帧优化:编译器可能会把变量按大小或类型分组,优化内存使用,这也可能导致变量之间出现额外的间隔。
而防止数组越界的措施,通常是编译时的静态检查(比如编译器报错数组下标越界),或者运行时的工具(比如AddressSanitizer),和数组之间的地址间隔没有直接关系。
二、修改指针指向不会改变数组本身的内存地址
先看你贴的代码和输出:
// more pointers #include <iostream> #include <string> using namespace std; int main () { int numbers[5]={1,2,3,4,5}; int alien=6; int * a; int * b; b=numbers; // b指向numbers数组的首地址 a=&alien; // a指向alien的地址 b=a; // 修改b的指向,现在b指向alien cout << "address of start of array numbers: " << b << endl; cout << "address of alien: " << a << endl; for (int i=0;i<5;i++){ cout << &numbers[i] << endl; cout << numbers[i] << endl; } return 0; }
输出:
address of start of array numbers: 0x79ab503a591c address of alien: 0x79ab503a591c 0x79ab503a5920 1 0x79ab503a5924 2 0x79ab503a5928 3 0x79ab503a592c 4 0x79ab503a5930 5
这里的关键误区是:指针b只是一个用来存储地址的变量,它和数组numbers本身是完全独立的。
你做了b=a这一步,只是把b里面存储的地址值改成了alien的地址,但这并不会对numbers数组产生任何影响:
numbers数组的内存是在程序进入main函数时,就被编译器分配在栈上的固定位置了,它的地址从一开始就确定了,不会因为你修改某个指针的指向而改变。- 你遍历
&numbers[i]时,输出的是数组元素本身的内存地址,自然还是原来的固定地址;而numbers[i]的值也没有被修改,所以输出的还是初始化的1-5。
简单说:指针就像一张写着地址的纸条,你修改纸条上的地址,并不会改变原来房子(数组)的位置,只是纸条现在指向了另一栋房子(alien)而已。
内容的提问来源于stack exchange,提问作者I Like
相关产品推荐
相关产品推荐

