在C中,移位运算符(<<
,>>
)是算术还是逻辑?
答案 0 :(得分:122)
向左移动时,算术和逻辑移位之间没有区别。向右移动时,移位类型取决于要移位的值的类型。
(作为那些不熟悉差异的读者的背景,1位的“逻辑”右移将所有位向右移动,并用0填充最左边的位。“算术”移位保留原始值最左边的位。当处理负数时,差异变得很重要。)
当移动无符号值时,&gt;&gt; C中的运算符是逻辑移位。当移动有符号值时,&gt;&gt;运算符是算术移位。
例如,假设一台32位机器:
signed int x1 = 5;
assert((x1 >> 1) == 2);
signed int x2 = -5;
assert((x2 >> 1) == -3);
unsigned int x3 = (unsigned int)-5;
assert((x3 >> 1) == 0x7FFFFFFD);
答案 1 :(得分:90)
根据K&R 2nd edition,结果与实施有关,适用于有符号值的右移。
Wikipedia说C / C ++'通常'对签名值实施算术移位。
基本上你需要测试你的编译器或不依赖它。我对当前MS C ++编译器的VS2008帮助表明他们的编译器进行了算术移位。
答案 2 :(得分:16)
就你所获得的班次类型而言,重要的是你正在转移的价值类型。一个典型的错误来源是当你将文字移动到比如掩盖位时。例如,如果你想删除无符号整数的最左边的位,那么你可以尝试这个作为你的掩码:
~0 >> 1
不幸的是,这会让你遇到麻烦,因为掩码将设置其所有位,因为被移位的值(~0)被签名,因此执行算术移位。相反,您希望通过明确地将值声明为无符号来强制进行逻辑移位,即通过执行以下操作:
~0U >> 1;
答案 3 :(得分:15)
这里有保证C中逻辑右移和算术右移的函数:
int logicalRightShift(int x, int n) {
return (unsigned)x >> n;
}
int arithmeticRightShift(int x, int n) {
if (x < 0 && n > 0)
return x >> n | ~(~0U >> n);
else
return x >> n;
}
答案 4 :(得分:6)
当你这样做的时候 - 左移1乘以2 - 右移1除以2
x = 5
x >> 1
x = 2 ( x=5/2)
x = 5
x << 1
x = 10 (x=5*2)
答案 5 :(得分:4)
好吧,我看了it up on wikipedia,他们有话要说:
然而,C只有一个右移 运算符,&gt;&gt;。许多C编译器选择 哪个权利转移到依赖 在什么类型的整数 转移;经常签名整数 使用算术移位移位, 和无符号整数被移位 使用逻辑转移。
所以听起来这取决于你的编译器。同样在那篇文章中,请注意左移与算术和逻辑相同。我建议在边框情况下使用一些有符号和无符号数字进行简单测试(当然是高位集)并查看编译器的结果。我还建议避免依赖它是一个或另一个,因为看起来C没有标准,至少如果它是合理的并且可能避免这种依赖。
答案 6 :(得分:0)
答案 7 :(得分:0)
左移<<
这在某种程度上很简单,无论何时使用移位运算符,它总是一个按位操作,因此我们不能使用double和float操作。每当我们将shift移一个零时,它总是被添加到最低有效位(LSB
)。
但是在右移>>
中,我们必须遵循一个额外的规则,并且该规则被称为&#34;签署位副本&#34;。 &#34;符号位副本&#34;的含义如果设置了最高有效位(MSB
),那么在再次右移之后,MSB
将被设置,如果它被重置,那么它再次被重置,意味着先前的值是否为零然后在移位之后再次,如果前一位为1则该位为零,然后在移位后它再次为1。此规则不适用于左移。
右移的最重要的例子,如果你将任何负数移到右移,然后在一些移位之后最终达到零,然后在此之后如果移动这个-1任何次数值将保持相同。请检查。
答案 8 :(得分:0)
GCC确实
for -ve - &gt;算术转移
for + ve - &gt;逻辑转变
答案 9 :(得分:-6)
根据许多c编译器:
<<
是算术左移或按位左移。>>
是算术右移位器按位右移。