Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C语言中关于位运算符的不同结果_C_Bitwise Operators_Bit Shift - Fatal编程技术网

C语言中关于位运算符的不同结果

C语言中关于位运算符的不同结果,c,bitwise-operators,bit-shift,C,Bitwise Operators,Bit Shift,为了在c中实现逻辑右移,我搜索了web并得到了以下c代码 int a, b, c; int x = -100; a = (unsigned) x >> 2; b = (0xffffffff & x) >> 2; c = (0x0 | x ) >> 2; 现在a和b都是逻辑右移结果(1006632960),但c仍然是算术右移结果(-25),有人能解释为什么吗?thx b = (0xffffffff & x) >> 2; 假设整数为

为了在c中实现逻辑右移,我搜索了web并得到了以下c代码

int a, b, c;
int x = -100;
a = (unsigned) x >> 2;
b = (0xffffffff & x) >> 2;
c = (0x0 | x ) >> 2;
现在a和b都是逻辑右移结果(1006632960),但c仍然是算术右移结果(-25),有人能解释为什么吗?thx

b = (0xffffffff & x) >> 2;
假设整数为32位,文字常量
0xffffffff
的类型为
unsigned int
,因为它太大,无法装入普通的
int
。然后,
&
介于
无符号int
int
之间,在这种情况下,根据定义,无符号类型获胜。因此,移位发生在无符号上;因此,它从左移0位

c = (0x0 | x ) >> 2;
0x0
的类型默认为
int
,因为它足够小,所以按位or发生在int上,下面的移位也发生在int上。有符号整数右移是由实现定义的,但大多数编译器会产生一个符号扩展的算术移位。

(unsigned)x
是unsigned int类型,因此它会得到一个逻辑移位

0xffffff
(假设32位int)的类型为unsigned int,因此
(0xffffffff&x)
的类型也为unsigned int,因此它会得到一个逻辑移位


0x0
是int类型,因此
(0x0 | x)
是int类型,并得到一个算术移位(好吧,它取决于实现)。

这都是关于
运算符的操作数类型的。如果操作数是负数,则右移将MSB设置为1。如果操作数是无符号的,则MSB位在右移位后始终为零

在第一个表达式中,操作数显式转换为无符号的

在第二个表达式中,
(0xffffffff&x)
表示无符号,因为
0xffffffff
明确表示无符号整数(这是有符号的
的溢出)


第三个示例中的OTOH
0x0
是有符号的(这是整数常量的默认值)。因此,整个操作数
(0x0 | x)
被认为是有符号的

让我困惑的是,为什么C编译器对0xFFFFFF和0x0的处理不同,它们不是都是数值常量吗?是的,但类型不同。不带后缀的十六进制常量的类型是
int
无符号
无符号长
无符号长
中能够表示值的第一个。0x0可以用整数表示,0xFFFFFF不是(至少对于32位整数来说,它是一个2^32-1的值,不是一个位模式)。任何文档都支持这一点,关于将文字常量视为大的无符号整数,小的有符号整数?C99标准第6.4.4.1节,第5小节?“整型常量的类型是可以表示其值的相应列表的第一个类型。”十进制常量的列表仅包含nsigned类型,但八进制和十六进制常量也可以是无符号的。