[英]Signed right shift: which compiler use logical shift
我用 Visual Studio、Ubuntu 的 GCC、英特尔编译器、MinGW 测试了右移。 所有的符号位都移位。 我猜 Xcode 的 GCC 也是如此。
我知道这种行为是特定于实现的,但看起来所有主要的桌面/服务器编译器都实现了算术转换。 是否有任何广泛使用的编译器不会改变符号位?
谢谢你。
C 运行在许多不同的体系结构上。 我的意思是很多不同的架构。 您可以在嵌入式 DSP 和 Cray 超级计算机上运行 C 代码。
人们认为理所当然的 C 标准中的大多数“实现定义”部分实际上只会破坏晦涩的架构。 例如,有 DSP 和 Cray 超级计算机,其中CHAR_BIT
是 32 或 64 之类的大数字。因此,如果您在 x86 上尝试您的代码,并且如果您喜欢使用 PowerPC、ARM 或 SPARC,则不太可能遇到任何非常奇怪的情况。 没关系。 如今,大多数代码将始终运行在具有二进制补码整数和算术移位的面向字节的体系结构上。 我毫不怀疑,在可预见的未来,任何新的 CPU 架构都是一样的。
但是让我们看看整数的两种最常见的表示形式:二进制补码和一个补码:
switch ((-1) >> 1) {
case 0:
case -0:
puts("Hello, one's complement world!");
// Possibly sign-magnitude.
break;
case -1:
puts("Hello, two's complement world!");
break;
default:
puts("Hello, computer without arithmetic shift");
break;
}
不要出汗。 当你想分割时,只需坚持/
,当你需要转移时,就坚持>>
。 即使是糟糕的编译器也擅长优化这些操作。 (请记住,如果x
是负数,则x/2 != x>>1
,除非您使用的是补码机,这几乎肯定不是真的。)
该标准确实保证如果(int) x
不是负数,则(int) x >> n == (unsigned) x >> n
,因此编译器没有太多空间可以做一些完全出乎意料的事情。
Cray C 编译器默认对有符号值进行逻辑右移,但有一个选项可以进行算术移位。
通常,可以安全地假设有符号右移是算术。
通常,它更多地取决于编译器使用的目标架构。 如果 arch 同时具有算术(有符号)和逻辑(无符号)移位指令,则该 arch 的 C 编译器将使用适当的。 另一方面,如果它只有逻辑移位,C 编译器将只使用它,即使它不会对负值“做正确的事情”,因为 C 规范允许编译器做任何事情。
据我所知, >> 运算符进行算术移位。 然而,对有符号和无符号整数执行移位的方式有所不同 - 有符号将扩展 MSB(通常是符号位)而无符号则不会(它们始终为非负,因此符号位始终为零)。
编辑: “通常”适用于我上面写的所有内容;)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.