首页 > 解决方案 > 负数右移不仅是未定义的,而且在clang中从一对多映射

问题描述

当我编译这个 C 代码并在我的机器上运行它十几次时,我每次都得到一个不同的 9 位负数。另一台机器上的另一个 clang 编译器产生 10 位不同的正整数。我期待一个奇怪的值,因为负数右移是未定义的,但令我惊讶的是该值不是一个唯一的数字。相反,我得到了具有相同输入的多个值。为什么这不是数学函数?

#include <stdio.h>
int main(void) {
  printf("%d", 1 >>  -1);
  return 0;
}

标签: cone-to-manyundefined-behavior

解决方案


因为没有定义行为,编译器(至少在 Clang 的情况下,见下文)选择不在参数将传递给的寄存器中放置任何内容printf。这导致寄存器具有准备 C 环境和调用的启动代码留下的任何值main。这恰好是启动期间使用的某个地址,它是由地址空间布局随机化随机化的,用于阻止对软件的攻击。

对 clang 生成的程序集的检查确认没有任何值被放置在寄存器 %esi 中,该值将用于此参数(使用 Apple LLVM 10.0.0 和 clang-1000.11.45.5,为其在 macOS 10.14.3 中的默认目标构建只有开关-O3)。

当然,其他编译器的行为可能会有所不同,因为 C 标准没有定义该行为;这仅解释了 OP 在有限情况下报告的观察结果。


推荐阅读