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

指针减法计算地址间距的疑问:为何结果是类型个数而非字节数?

为什么C语言中指针减法得到的是元素个数而非字节数?

这是个非常常见的C语言指针算术误区,我来帮你理清楚背后的标准规定和实际原因:

先拆解你观察到的现象

你遇到的结果完全符合C语言的指针减法规则:

  • 当a和b是uint32_t类型时:假设两个变量的地址字节差是4(大概率是栈对齐导致的相邻分配),指针减法&b - &a会自动除以sizeof(uint32_t)(也就是4),所以结果是4/4=1。
  • 当a和b是uint8_t类型时:同样地址字节差为4,指针减法除以sizeof(uint8_t)(也就是1),结果就是4/1=4。

这里的核心结论是:指针减法的结果是两个指针之间的元素个数差值,而非原始字节数差值。

C语言标准的明确规定

以C11标准为例,6.5.6 加法运算符章节对指针减法的行为做了清晰定义:

当两个指针相减时,两者都必须指向同一个数组对象的元素,或者指向该数组对象的最后一个元素之后的位置;结果是两个数组元素的下标之差。结果的大小由实现定义,其类型是有符号整数类型ptrdiff_t。如果结果无法用该类型的对象表示,则行为未定义。换句话说,如果表达式P和Q分别指向数组对象的第i个和第j个元素,那么表达式(P)-(Q)的值为i-j,前提是该值能放入ptrdiff_t类型的对象中。此外,如果表达式P指向数组对象的一个元素或最后一个元素之后的位置,表达式Q指向同一数组对象的最后一个元素,那么表达式((Q)+1)-(P)的值与((Q)-(P))+1以及-((P)-((Q)+1))相同;如果P指向数组对象的最后一个元素之后的位置,则该值为零,即使(Q)+1并不指向数组对象的元素。

补充说明

你可能会疑惑:我的例子里a和b不是数组元素,为什么规则还适用?
实际上,C标准允许将单个变量视为长度为1的数组的唯一元素,所以两个相邻的局部变量(在编译器分配的连续地址空间中)可以类比为数组的两个元素,指针减法的规则同样生效。另外,你例子中地址字节差固定为4,大概率是因为编译环境开启了栈对齐(比如32位系统默认4字节对齐),即使是uint8_t类型的变量,也会被分配4字节的栈空间。

如何得到你预期的字节数差值

如果你想计算两个地址之间的原始字节数,可以把指针强制转换为uint8_t*(或char*,因为char类型的大小固定为1字节)再做减法:

uint32_t a, b;
uint32_t length = (uint8_t*)&b - (uint8_t*)&a; // 直接得到字节数差值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:29:17