签名右移:哪个编译器使用逻辑移位

我使用Visual Studio,Ubuntu的GCC,英特尔编译器,MinGW测试了右移。 所有移位的符号位。 我猜Xcode的GCC也是如此。

我知道这种行为是特定于实现的,但看起来所有主要的桌面/服务器编译器都实现了算术移位。 是否有任何广泛使用的编译器不会在符号位中移位?

谢谢。

C运行在许多不同的体系结构上。 我的意思是很多不同的架构。 您可以在嵌入式DSP和Cray超级计算机上运行C代码。

人们认为理所当然的C标准的大多数“实现定义”部分实际上只会破坏模糊的架构。 例如,有些DSP和Cray超级计算机,其中CHAR_BIT是像32或64那么大的东西。所以如果你在x86上试用你的代码,也许你是慷慨的PowerPC,ARM或SPARC,你就不太可能遇到任何非常奇怪的案件。 那没关系。 如今,大多数代码总是在面向字节的架构上运行,具有二进制补码整数和算术移位。 毫无疑问,在可预见的未来,任何新的CPU架构都是一样的。

但是让我们看一下整数的两个最常见的表示forms:二元补码和一元补码:

 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; } 

不要出汗。 只需坚持/当你想分开时, >>当你需要换class时。 即使糟糕的编译器也擅长优化这些操作。 (并记住x/2 != x>>1如果x是负数,除非你在一个补码机上,这几乎肯定不是真的。)

该标准确保if (int) x不是负数,然后(int) x >> n == (unsigned) x >> n ,因此编译器没有足够的空间来做一些完全出乎意料的事情。

通常,它更多地取决于编译器使用的目标体系结构。 如果arch具有算术(带符号)和逻辑(无符号)移位指令,那么该arch的C编译器将使用适当的。 另一方面,如果它只有逻辑移位,C编译器就会使用它,即使它没有为负值做“正确的事情”,因为C规范允许编译器做任何事情。

默认情况下,Cray C编译器对有符号值进行逻辑右移,但是可以选择进行算术移位。

通常,可以安全地假设有符号右移是算术运算。

据我所知,>>运算符进行算术移位。 然而,对有符号整数和无符号整数执行移位之间存在差异 – 有符号将扩展MSB(通常是符号位)而无符号则不会(它们总是非负的,因此符号位始终为零)。

编辑: “通常”应用于我上面写的所有内容;)。