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

为何两个C++指针表达式输出不同的内存地址?

问题

以下代码运行后输出了不同的内存地址,原本预期两个表达式返回相同地址,请问原因是什么?

#include <iostream>

int main() {

    float (*arrayName)[2][4][4];

    auto address1 = (**arrayName)[1]; // 0x10
    auto address2 = (*arrayName)[1][0]; // 0x40
    std::cout << "Address1: " << address1 << std::endl;
    std::cout << "Address2: " << address2 << std::endl;
}

注:0x40是期望得到的地址,在线C++编译器测试时两者均输出0x10,但在RHEL7开发虚拟机中得到0x10和预期的0x40。

原因分析

1. 明确指针类型

float (*arrayName)[2][4][4]是一个指向三维float数组的指针,这个三维数组的维度是[2][4][4],每个float元素占4字节。

2. 拆解两个地址表达式

表达式(**arrayName)[1]的计算过程:

  • 第一次解引用*arrayName:得到整个三维数组[2][4][4],此时数组会自动退化为指向其第一个元素的指针——也就是指向[4][4]二维数组的指针(类型为float (*)[4][4])。
  • 第二次解引用**arrayName:得到第一个[4][4]二维数组,再次退化为指向其第一个元素的指针——也就是指向[4]一维数组的指针(类型为float (*)[4])。
  • 最后[1]:对这个一维数组指针做偏移,偏移量是1个[4]数组的大小(4个float × 4字节 = 16字节,即0x10),所以最终地址是原地址 + 0x10。

表达式(*arrayName)[1][0]的计算过程:

  • *arrayName是三维数组,退化为指向[4][4]二维数组的指针(类型float (*)[4][4])。
  • (*arrayName)[1]:偏移1个[4][4]二维数组的大小(4×4个float ×4字节=64字节,即0x40),得到第二个[4][4]二维数组,随后退化为指向其第一个[4]一维数组的指针。
  • [0]:偏移0个[4]数组,所以最终地址是原地址 + 0x40。

3. 不同环境结果差异的原因

代码中的arrayName是未初始化的野指针,没有指向任何有效的内存空间,这属于C++中的未定义行为——不同编译器、不同操作系统对未定义行为的处理逻辑可能完全不同,所以才会出现在线编译器和RHEL7虚拟机结果不一致的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 18:33:33