C语言 从普通指针中减去 NULL 指针会生成算术右移



这是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 倍以上。

最新更新