在 C 中,在 32 位机器上,我只是想知道给定的1>>31
返回值是否是有符号整数,因为对于 2 的补码,在进行右移(算术)时,会复制符号位以给出结果-1
1
1111 1111 1111 1111 1111 1111 1111 1111
在 C 中,在 32 位机器上,我只是想知道给定的1>>31
返回值是否是有符号整数,因为对于 2 的补码,在进行右移(算术)时,会复制符号位以给出结果-1
1
1111 1111 1111 1111 1111 1111 1111 1111
不,在任何符合要求的实现中,结果都将为零。
C99, 6.5.7/5(“按位移位运算符”)状态:
E1 >> E2 的结果是 E1 右移 E2 位位置。如果 E1 具有无符号类型或 E1 具有有符号类型和非负值,则结果的值是 E1 / 2^E2 的商的整数部分。如果 E1 具有带符号类型和负值,则结果值是实现定义的。
由于是非负的,因此结果是其明显为零1
的积分商。1 / (2^31)
结果将为零,因为整数 1 的符号位(最高有效位)为 0:
0000 0000 0000 0000 0000 0000 0000 0001
^
的结果1>>31
为零,因为 1 的符号位为 0。
但是,您不能指望被复制的符号位,因为根据 K&R 第二版,结果是为有符号值的右移实现定义的。
以下代码有助于确定右移是否是有符号整数的算术,对于使用int
s 的二进制补码表示的实现。
#include <stdio.h>
//below function returns 1 if system is little endian, 0 otherwise
int is_little_endian() { //checks endianness
short x = 0x0100; //256
char *p = (char*) &x;
if (p[0] == 0) {
return 1;
}
return 0;
}
/* Below function returns 1 if shifts are arithmetic, 0 otherwise.
It checks whether the most significant bit is 1 or 0, for an int which
had most the significant bit as 1 prior to the right shift. If the MSB
is 1 after the bit shift, then the (unsigned) value of the most
significant Byte would be 255.
*/
int int_shifts_are_arithmetic() {
int x = -2;
x = x >> 1 ;
char *px = (char*)&x;
if (is_little_endian()) {
unsigned char *upx = (unsigned char*)&px[(int)sizeof(int) - 1];
if (upx[0] == 255) return 1;
return 0;
} else { //big endian
unsigned char* upx = (unsigned char*)px;
if (upx[0] == 255) return 1;
return 0;
}
}
int main() {
if (int_shifts_are_arithmetic()) {
printf("Shifts are arithmetic\n");
}
else {
printf("Shifts are not arithmetic\n");
}
return 0;
}