You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

栈上数组内存存储疑问:变量地址与值为何完全一致?

栈上数组与动态数组的地址差异解析

栈上数组的地址特性

在栈上创建数组时,以下三个地址值完全相等:

  • 栈上数组变量自身的地址(&automaticArray)
  • 数组变量的值(隐式转换后的指针,automaticArray)
  • 数组首元素的地址(&automaticArray[0])

栈上创建类型为T、大小为N的数组时,栈中直接分配sizeof(T)*N字节的连续空间存储数组元素,并没有额外存储指向数组的指针。示例代码:

#include <bits/stdc++.h>

using namespace std;

int main() {
    int automaticArray[5] {1, 2, 3, 4, 5};
    cout << "变量值 = " << automaticArray 
         << ", 变量地址 = " << &automaticArray 
         << ", 首元素地址 = " << &automaticArray[0] << endl;
}

输出中三个地址完全一致的核心原因:数组变量automaticArray是数组类型的标识符,当它被当作指针使用时(比如输出到cout),会自动隐式转换为指向数组首元素的指针;而&automaticArray取的是数组变量的地址,由于数组本身就直接存储在栈的这个地址上,所以它和首元素的地址完全重合——数组的起始地址就是它自身的地址,也是首元素的地址。

动态数组的地址特性

在动态内存(堆)中创建数组时,栈上仅存储一个8字节的指针变量(64位系统下),这个指针指向堆中实际的数组空间。因此:

  • 栈上指针变量的地址(&dynamicArray)是栈中的位置
  • 指针变量的值(dynamicArray)是堆中数组的起始地址
  • 数组首元素的地址(&dynamicArray[0])等于指针变量的值,即堆中数组的起始地址

此时栈上变量的地址和另外两个值必然不同。示例代码:

#include <bits/stdc++.h>

using namespace std;

int main() {
    int* dynamicArray = new int[5] {0};
    cout << "变量值 = " << dynamicArray 
         << ", 变量地址 = " << &dynamicArray 
         << ", 首元素地址 = " << &dynamicArray[0] << endl;
}

疑问解答:栈上数组不存在额外存储的指针

以int数组为例,栈上数组的前8字节并没有同时存储指针和元素——因为根本不存在这个额外的指针:

  • 数组变量automaticArray不是指针变量,它是数组类型的实例。当你使用automaticArray时,编译器会自动将其转换为指向首元素的指针,但这个指针是编译期临时生成的语义,并非在栈上实际存储了一个8字节的指针值。
  • 栈上只有数组的5个int元素(共20字节),&automaticArray就是这个20字节空间的起始地址,和&automaticArray[0]完全一致,因为首元素就位于这个空间的起始位置。

查看汇编代码可以更直观验证:栈上数组的初始化是直接将元素值写入栈的连续地址,没有任何存储指针的指令;而动态数组则会先调用operator new分配堆空间,再将返回的地址存入栈上的指针变量中。


内容的提问来源于stack exchange,提问作者Bychkov Arthur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 16:56:01