我用 Visual Studio、Ubuntu 的 GCC、Intel 编译器、MinGW 测试了右移。全部移位符号位。我猜 Xcode 的 GCC 也是如此。
我知道行为是特定于实现的,但看起来所有主要的桌面/服务器编译器都实现了算术移位。是否有任何广泛使用的编译器不会改变符号位?
谢谢你。
我用 Visual Studio、Ubuntu 的 GCC、Intel 编译器、MinGW 测试了右移。全部移位符号位。我猜 Xcode 的 GCC 也是如此。
我知道行为是特定于实现的,但看起来所有主要的桌面/服务器编译器都实现了算术移位。是否有任何广泛使用的编译器不会改变符号位?
谢谢你。
C 在许多不同的架构上运行。我的意思是很多不同的架构。您可以在嵌入式 DSP 和 Cray 超级计算机上运行 C 代码。
人们认为理所当然的 C 标准的大多数“实现定义”部分实际上只在晦涩的架构上中断。例如,有CHAR_BIT
32 或 64 之类的 DSP 和 Cray 超级计算机。因此,如果您在 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/2 != x>>1
ifx
是负数,除非你在一个补码机器上,这几乎肯定不是真的。)
该标准确实保证 if(int) x
不是负数,(int) x >> n == (unsigned) x >> n
因此,编译器没有太多空间可以做一些完全出乎意料的事情。
通常它更多地取决于编译器使用的目标架构。如果拱门同时具有算术(有符号)和逻辑(无符号)移位指令,则该拱门的 C 编译器将使用合适的指令。另一方面,如果它只有逻辑移位,C 编译器将只使用它,即使它没有为负值“做正确的事情”,因为 C 规范允许编译器做任何事情。
Cray C 编译器默认对有符号值进行逻辑右移,但可以选择进行算术移位。
通常,可以安全地假设带符号的右移是算术的。
据我所知,>> 运算符进行算术移位。然而,有符号和无符号整数的移位方式有所不同——有符号将扩展 MSB(通常是符号位),而无符号则不会(它们始终为非负数,因此符号位始终为零)。
编辑:将“通常”应用于我上面写的所有内容;)。