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

C++中多维数组与指针的地址及值相关疑问

int main()
{
    int A[2][2][2] =
    {
    {{1, 2}, {3, 4}},
    {{4, 5}, {5, 6}}
    };
    cout << A << endl; // 假设输出为400
    cout << *A << endl; // 400
    cout << **A << endl; // 400
    cout << ***A << endl; // 1

    cout << &A[0][1] << endl; // 408
}

疑问

数组与指针有诸多相似特性,我认为A是指向二维int数组的指针,指向地址400,解引用一次得到指向一维数组的指针仍指向400。现存在两个疑问:

  • 普通指针解引用会得到指向地址存储的值,但多维数组并非如此?地址400存储的值是1,但A、*A、**A都输出400。
  • 对于最后一行cout,A[0][1]是指向int的指针,解引用后得到地址408处的值3;但& A[0][1]输出408,该地址存储的是int值3,为何看起来像是存储指针类型?希望得到相关原理的解释。

原理解释

问题1:多维数组名的隐式转换逻辑

C++中数组名在绝大多数语境下会隐式转换为指向数组首元素的指针,但数组本身和指针并非同一事物,这点在多维数组中表现得更清晰:

  • A是int[2][2][2]类型的三维数组,用cout输出时,它会自动转换成指向其首元素的指针(类型为int(*)[2][2],即指向二维数组的指针),指向的地址是数组首元素的起始地址400,因此输出400。
  • 解引用*A得到的是A的首元素,也就是int[2][2]类型的二维数组。这个二维数组名同样会隐式转换为指向其首元素的指针(类型为int(*)[2],即指向一维数组的指针),而该一维数组的起始地址同样是400,所以输出还是400。
  • 再解引用**A得到的是二维数组的首元素,也就是int[2]类型的一维数组。这个一维数组名又会自动转换成指向其首元素的指针(类型为int*),指向的起始地址依旧是400,因此输出400。
  • 只有***A是对指向int的指针做解引用,直接取出地址400处存储的int值1,所以输出1。

普通指针解引用是直接取指向地址的内容,但多维数组的每一层解引用得到的还是数组类型,而数组名又会自动转成指针,因此才会出现多次解引用后输出地址的情况,本质和普通指针逻辑一致,只是多了数组到指针的隐式转换步骤。

问题2:&A[0][1]的类型与地址含义

首先纠正一个误解:A[0][1]不是指针,它是int[2]类型的一维数组。

  • A[0]是三维数组的第一个元素(int[2][2]类型的二维数组),A[0][1]是这个二维数组的第二个元素(int[2]类型的一维数组),它的起始地址是408(因为A[0][0]包含两个int,占8字节,400+8=408)。
  • 取&A[0][1]得到的是指向这个一维数组的指针(类型为int(*)[2])。cout输出指针时只会打印其存储的地址值,也就是该一维数组的起始地址408,和这个地址里存储的int值3没有关系——指针的地址值就是它指向对象的起始位置,不管对象是int还是数组。

你觉得“像是存储指针类型”是混淆了指针的地址值和它指向的内容:&A[0][1]本身是一个指针,它的值是408,而408这个地址里存储的是int[2]数组的第一个元素3,两者是完全不同的概念。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 01:03:23