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

普通指针减去NULL指针为何会生成算术右移(sar)指令?

为什么指针运算p - (int*)NULL会生成sar rax, 2指令?

让我们一步步拆解这个问题,从C标准规则到汇编指令的本质:

1. 先看懂C代码里的指针运算逻辑

先看你的代码:

int main() { int i = 10, *p = &i; printf("%ld", p - (int *) NULL); }

这里的核心运算p - (int*)NULL,遵循C语言的指针减法规则:

  • 只有同类型指针相减时,结果才是它们之间相隔的元素个数,而不是字节数。
  • (int*)NULL本质是把地址0转换成int*类型的指针,所以这个运算的实际意义是:计算指针p的地址值相对于地址0的int元素数量。

举个例子:如果&i的地址是0x1004,那0x1004 / 4 = 0x401(因为int占4字节),这个结果就是p - (int*)NULL的值。

2. 为什么用sar rax, 2来实现这个计算?

在x86_64平台上,int的大小通常是4字节(32位),所以元素个数 = 指针地址值 ÷ 4。而sar rax, 2是算术右移2位的汇编指令,它和除以4的关系是:

  • 对于正数来说,算术右移n位等价于除以2^n。右移2位就是除以2^2=4,和我们需要的计算完全匹配。
  • 为什么用算术右移(sar)而不是逻辑右移(shr)?因为C语言中指针减法的结果类型是ptrdiff_t,这是一个有符号整数类型。编译器会把指针地址当作有符号数处理,算术右移会保留符号位,能正确处理负数地址(虽然用户空间几乎不会遇到,但内核地址可能存在负数情况),而逻辑右移会补0,对负数地址处理不正确。

所以编译器把指针地址加载到rax寄存器后,用sar rax,2一步完成“除以4得到元素个数”的计算,这就是两者的关联。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:57:43