我指的是这篇文章特别是这一部分
5位超大移位量:将 uint32_t 移位 32 位或更多位是未定义的。我的猜测是,这是因为不同 CPU 上的底层移位操作对此做了不同的事情:例如,X86 将 32 位移位量截断为 5 位(因此 32 位移位与移位 32 位相同) 0 位),但 PowerPC 将 32 位移位截断为 6 位(因此移位 32 会产生零)。由于这些硬件差异,C 语言完全未定义该行为(因此在 PowerPC 上移位 32 位可能会格式化您的硬盘驱动器,“不”保证产生零)。消除这种未定义行为的代价是编译器必须为变量移位发出额外的操作(如“与”),这将使它们在普通 CPU 上的成本增加两倍。
那些
和6位是什么?
n
:
x86 CPU 将移动n & 31
n
的低五位的值是什么);而PowerPC 将移动 n & 63
n
的低六位的值)。
n
次,无论
n
可能是什么。但它也是一款已有 45 年历史的纯实模式 16 位处理器,因此您可能不会瞄准它。<<
或
>>
运算符的第二个参数。最大合理移位为 31,适合 5 位数字,因此 CPU 会屏蔽掉较高位。换句话说,在 x86 CPU 上uint32_var << shift_amt
被视为
uint32_var << (shift_amt & 0x1f)
因此,如果您尝试移动 32 位,它实际上会移动 0 位,而不是移走所有内容。
PowerPC 类似,但掩码为
0x3f
,因此移位量在达到 64 位之前不会回绕。
由于不同的 CPU 的行为不同,并且他们不希望编译器必须生成检查移位量是否太大的代码,因此他们只是声明这是未定义的行为。避免移动过多是程序员的责任。