英文:
What are the 5bits and the 6bits in when bit shifting by the size of the integer?
问题
在这篇文章中,提到了关于位移操作的一段内容。其中提到了“5位”和“6位”。
在X86架构中,对于32位的位移操作,实际上只使用了5位来表示位移的数量。这意味着,如果将一个32位的数左移32位或更多位,实际上相当于左移0位。
而在PowerPC架构中,对于32位的位移操作,使用了6位来表示位移的数量。这意味着,如果将一个32位的数左移32位,结果将为零。
这两种不同的硬件架构对于位移操作的处理方式不同,因此C语言中对于超出位移范围的操作行为是未定义的。为了消除这种未定义行为,编译器需要额外生成一条操作指令(比如使用“与”操作),这会导致变量位移操作在常见的CPU上变得更加耗时。
英文:
I'm referring to this article specifically this part
> Oversized Shift Amounts: Shifting a uint32_t by 32 or more bits is undefined. My guess is that this originated because the underlying shift operations on various CPUs do different things with this: for example, X86 truncates 32-bit shift amount to 5 bits (so a shift by 32-bits is the same as a shift by 0-bits), but PowerPC truncates 32-bit shift amounts to 6 bits (so a shift by 32 produces zero). Because of these hardware differences, the behavior is completely undefined by C (thus shifting by 32-bits on PowerPC could format your hard drive, it is not guaranteed to produce zero). The cost of eliminating this undefined behavior is that the compiler would have to emit an extra operation (like an 'and') for variable shifts, which would make them twice as expensive on common CPUs.
What are those 5 bits and 6 bits?
答案1
得分: 5
这段引文声称,硬件操作可以将数据按 n
位进行移位:
- x86 CPU 将按
n & 31
位进行移位(即n
的低五位的值); - PowerPC 将按
n & 63
位进行移位(即n
的低六位的值)。
- 原始的 8086 实际上并不是这样做的,如果我没记错的话。它会一直移位,直到按
n
次移动一个位,无论n
是多少。但它也是一个45年历史的仅支持实模式的16位处理器,所以你可能不会针对它进行开发。
英文:
The quote alleges, close enough to accurately* that the hardware operations to shift by n
:
- x86 CPUs will shift by
n & 31
places (i.e. whatever the value is of the low five bits ofn
); whereas - PowerPCs will shift by
n & 63
places (i.e. the value of the low six bits ofn
).
* the original 8086 doesn't actually do this, if memory serves. It'll just keep going until it has shifted by a single bit, n
times, whatever n
might be. But it's also a 45-year-old real-mode-only 16-bit processor so you probably weren't going to target it.
答案2
得分: 2
他们正在讨论<<
或>>
运算符的第二个参数。最大合理的位移是31,它可以用一个5位的数字表示,所以CPU会屏蔽掉高位。换句话说,在x86 CPU上,
uint32_var << shift_amt
被视为
uint32_var << (shift_amt & 0x1f)
所以如果你尝试进行32位的位移,实际上它会进行0位的位移,什么也不做。
PowerPC类似,但掩码是0x3f
,所以位移量直到达到64位才会回绕。
由于不同的CPU行为不同,并且他们不希望编译器生成检查位移量是否过大的代码,所以他们简单地声明这是未定义行为。避免进行过大的位移是程序员的责任。
英文:
They're talking about the second argument to the <<
or >>
operator. The maximum reasonable shift is 31, and that fits into a 5-bit number, so the CPU masks away the higher bits. In other words, on an x86 CPU
uint32_var << shift_amt
is treated as
uint32_var << (shift_amt & 0x1f)
So if you try to shift by 32 bits, instead of shifting everything away, it actually shifts by 0 bits and does nothing.
PowerPC is similar, but the mask is 0x3f
, so the shift amount doesn't wrap around until it gets to 64 bits.
Since different CPUs act differently, and they didn't want compilers to have to generate code that checks if the shift amount is too large, they simply declared that this is undefined behavior. It's the programmer's responsibility to avoid shifting by too much.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论