我使用Visual Studio,Ubuntu的GCC,英特尔编译器,MinGW测试了右移。所有移位的符号位。我猜Xcode的GCC也是如此。
我知道这种行为是特定于实现的,但看起来所有主要的桌面/服务器编译器都实现了算术转换。是否有任何广泛使用的编译器不会在符号位中移位?
谢谢。
答案 0 :(得分:15)
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/2 != x>>1
x
如果(int) x
是否定的,除非您使用的是补充机器,这几乎肯定不是真的。)
标准确实保证如果(int) x >> n == (unsigned) x >> n
不是负数,那么{{1}},因此编译器没有足够的空间来做一些完全出乎意料的事情。
答案 1 :(得分:2)
通常,它更多地取决于编译器使用的目标体系结构。如果arch同时具有算术(带符号)和逻辑(无符号)移位指令,那么该arch的C编译器将使用适当的任何一个。另一方面,如果它只有逻辑移位,C编译器就会使用它,即使它没有为负值“做正确的事情”,因为C规范允许编译器做任何事情。
答案 2 :(得分:1)
Cray C编译器默认对有符号值进行逻辑右移,但是可以选择进行算术移位。
通常,可以安全地假设签名的右移是算术运算。
答案 3 :(得分:-2)
据我所知,>>运算符进行算术运算。然而,对有符号整数和无符号整数执行移位之间存在差异 - 有符号将扩展MSB(通常是符号位)而无符号则不会(它们总是非负的,因此符号位始终为零)。 / p>
编辑:将“通常”应用于我上面写的所有内容;)。