有符号右移:哪个编译器使用逻辑移位
我使用 Visual Studio、Ubuntu 的 GCC、Intel 编译器、MinGW 测试了右移。全部移位符号位。我猜 Xcode 的 GCC 也是这样做的。
我知道该行为是特定于实现的,但看起来所有主要的桌面/服务器编译器都实现了算术移位。是否有广泛使用的编译器不会移动符号位?
谢谢。
I tested right shift with Visual Studio, Ubuntu's GCC, Intel compiler, MinGW. All shift in the sign bit. I guess Xcode's GCC does the same.
I know that the behavior is implementation specific, but it looks like that all major desktop/server compilers implement arithmetic shift. Are there any widely used compiler that doesn't shift in the sign bit?
Thank you.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
C 运行在许多不同的体系结构上。我的意思是很多不同的架构。您可以在嵌入式 DSP 和 Cray 超级计算机上运行 C 代码。
人们认为理所当然的 C 标准中的大多数“实现定义”部分实际上只会在模糊的体系结构上出现问题。例如,在 DSP 和 Cray 超级计算机中,
CHAR_BIT
是像 32 或 64 这样的大数字。因此,如果您在 x86 上尝试代码,或者如果您慷慨的话,可以使用 PowerPC、ARM 或SPARC,您不太可能遇到任何真正奇怪的情况。没关系。如今,大多数代码始终在具有二进制补码整数和算术移位的面向字节的体系结构上运行。我毫不怀疑在可预见的将来任何新的 CPU 架构都将是相同的。但让我们看一下整数的两种最常见的表示形式:二进制补码和个人补码:
别担心。当你想要分割时,只需坚持
/
,当你需要移动时,坚持>>
。即使是糟糕的编译器也擅长优化这些操作。 (请记住,如果x
为负,则x/2 != x>>1
,除非您使用的是补码机器,这几乎肯定不是真的.)该标准确实保证如果
(int) x
不为负数,则(int) x >>> n == (无符号) x >> n
,因此编译器没有足够的空间来做一些完全意想不到的事情。C runs on a lot of different architectures. I mean a lot of different architectures. You can get C code running on an embedded DSP and on a Cray supercomputer.
Most of the "implementation-defined" parts of the C standard that people take for granted really only do break on obscure architectures. For example, there are DSPs and Cray supercomputers where
CHAR_BIT
is something huge like 32 or 64. So if you try out your code on an x86, and maybe if you're generous a PowerPC, ARM, or SPARC, you're not likely to run into any of the really weird cases. And that's okay. Most code these days will always run on a byte-oriented architecture with twos-complement integers and arithmetic shifts. I have no doubt that any new CPU architectures in the foreseeable future will be the same.But let's look at the two most common representations for integers: two's complement and ones' complement:
Don't sweat it. Just stick to
/
when you want to divide, and>>
when you need to shift. Even bad compilers are good at optimizing these operations. (And remember thatx/2 != x>>1
ifx
is negative, unless you're on a ones' complement machine, which is almost certainly not true.)The standard does guarantee that if
(int) x
is not negative, then(int) x >> n == (unsigned) x >> n
, so there is not a lot of room for a compiler to do something completely unexpected.一般来说,它更多地取决于编译器使用的目标体系结构。如果架构同时具有算术(有符号)和逻辑(无符号)移位指令,则该架构的 C 编译器将使用合适的指令。另一方面,如果它只有逻辑移位,C 编译器将只使用它,即使它不会对负值“做正确的事情”,因为 C 规范允许编译器做任何事情。
Generally it depends more on the target architecture that the compiler used. If the arch has both arithmetic (signed) and logical (unsigned) shift instructions, then C compilers for that arch will use whichever is appropriate. On the other hand, if it has only logical shifts, the C compiler will just use that, even though it doesn't 'do the right thing' for negative values, as the C spec allows the compiler to do anything.
默认情况下,Cray C 编译器对有符号值进行逻辑右移,但可以选择进行算术移位。
一般来说,可以安全地假设有符号右移是算术运算。
Cray C compiler does logical right shift on signed values by default, but there's an option to do arithmetic shift instead.
Generally, it's safe to assume that signed right shift is arithmetic.
据我所知,>>运算符进行算术移位。然而,对有符号整数和无符号整数执行移位的方式存在差异 - 有符号整数将扩展 MSB(通常是符号位),而无符号则不会(它们始终为非负数,因此符号位始终为零)。
编辑:将“通常”应用于我上面写的所有内容;)。
As far as I can tell, the >> operator does arithmetic shift. There is however a difference between how the shift is performed for signed and unsigned integers - signed will extend the MSB (which usually is a sign bit) and unsigned will not (they are always non-negative so sign bit is always zero).
EDIT: apply "usually" to everything I wrote above ;).