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

C语言二级指针错误解引用遍历数组的异常输出咨询

二级指针错误解引用的输出成因分析

首先明确C语言下标运算的核心规则:任何arr[i]的写法,都完全等价于*(arr + i),指针做算术运算的偏移单位,是指针指向类型的大小,和其他因素无关。

你的代码里d是int**类型,它指向的是栈上单个int*类型变量p,从C语言标准的合法边界来说,你最多只能合法访问d[0](也就是p本身),循环里访问d[1]到d[9]全是越界的栈内存访问,属于标准定义的未定义行为。

为什么会输出间隔的数组元素

你这次的输出完全是当前编译运行环境下的栈布局巧合,可以从输出反推你当前环境的特征:

  • 你运行的是64位程序,sizeof(int*) == 8,sizeof(int) == 4,所以d每加1,实际内存地址向后偏移8字节,刚好跨过2个int类型的数组元素长度。
  • 你当前的无优化编译版本中,栈上局部变量的排布刚好满足:p变量(也就是d指向的内存位置)向后(指针加法方向)紧挨着存放的就是a数组的元素。

对应你循环里的取值逻辑完全吻合:

  • i=0:访问d[0],是合法读取p存储的值,也就是a数组的首地址,和你第一行打印的p值一致。
  • i=1:地址偏移8字节,刚好落到a[0]的起始位置,读8字节长度的指针值时,因为你错误使用%d格式打印(%d只取4字节内容按整数解析),小端序下刚好读到低4字节存储的a[0]值10。
  • i=2:地址再偏移8字节,跨过了a[1],落到a[2]的位置,读到值30。
  • 后续i=3、4、5同理,每次跳2个数组元素,依次读到a[4]=50、a[6]=70、a[8]=90。
  • 再往后的地址越过了a数组的范围,读到的是栈上其他变量、栈保护值、函数返回地址之类的内存内容,就是你看到的无规律数值。

这种行为的性质

  • 它不是真正意义上的“随机值”,输出结果完全由当前环境决定:编译器版本、优化等级、栈保护开关、变量定义顺序、操作系统的栈排布规则、地址空间随机化机制都会改变内存布局,换任何一个条件,输出结果都会完全不同,甚至可能直接触发内存访问错误导致程序崩溃。
  • 它不是完全没有研究价值:顺着这个输出倒推原理,能帮你彻底搞懂指针算术、下标运算、栈内存排布、未定义行为的核心逻辑,但绝对不能在生产代码里依赖这种行为,它不具备任何可移植性,不属于C语言标准保证的合法行为。

另外提一句你代码里的额外问题:打印指针值应该用%p格式符,并且把参数强转为void*,用%d打印指针本身也是未定义行为,在64位环境下会因为参数长度不匹配导致printf读取错误,也会干扰输出结果。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 07:21:27