这是C代码。
int main() {
int i = 10, *p = &i;
printf("%ld", p - (int *) NULL);
}
对于指针算术部分,"gcc"和"clang"都在其程序集输出中生成"sar rax,2"指令。有人可以解释一下在这种情况下指针算术如何与算术右移相关。
移 2 是除以 4 的快速方法。 4 是您int
大小。
两个指针到int
的距离是对应于int
指针的两个char
指针的距离除以int
大小(请记住,将整数添加到指针时,整数按指针目标大小缩放,因此当您进行差异时,您需要撤消此缩放(。
从技术上讲,您不应该减去两个不相关的指针(或用"%ld"
而不是正确的"%zd"
打印差异(,因为这是未定义的行为 - 该标准只允许您区分指向同一对象的指针或只是过去。尽管如此,一个通用的int*
差异函数本身没有这种未定义的行为:
#include <stddef.h>
ptrdiff_t diff_int_ptr(int *A, int *B)
{
return A-B;
}
仍将转换为等效的
ptrdiff_t diff_int_ptr(int *A, int *B)
{
return ((char*)A - (char*)B) >> lg2(sizeof(int));
//strength reduced from: return ((char*)A - (char*)B) / sizeof(int)
//which is possible iff sizeof(int) is a power of 2
}
在优化编译器(X86-64 GCC 和 Clang 的 Godbold 链接(上,移位通常比现代机器上的除法快 10 倍以上。