右操作数为负时按位移运算符的行为
在C&C ++中,如果右操作数在使用>>
和<<
(右移&左移操作符)时为负,程序的行为是不确定的。 考虑以下程序:
#include <iostream>
int main()
{
int s(9);
std::cout<<(s<<-3);
}
g ++提供以下警告:
[Warning] left shift count is negative [enabled by default]
MSVS 2010给出以下警告:
warning c4293: '<<' : shift count negative or too big, undefined behavior
现在我很好奇Java和C#中会发生什么?
我试过下面的程序
class left_shift_nagative
{
public static void main(String args[])
{
int a=3;
System.out.println(a<<-3);
System.out.println(a>>-3);
}
}
方案结果:
1610612736
0
C#轮到了:
namespace left_shift_nagative
{
class Program
{
static void Main(string[] args)
{
int s = 3;
Console.WriteLine(s << -3);
Console.WriteLine(s >> -3);
}
}
}
输出:
1610612736
0
输出如何1610612736? 这里发生了什么? Java语言规范(JLS)和C#语言规范或标准对此有何评论? 在Java和C#中给出负移位计数时,<<和>>操作符是如何工作的? 如何在使用右移时获得输出0? 我真的很困惑。
我将回答Java部分(不能说C#,但它可能是相同的)。
移位运算符>>
和<<
在JLS第15.19节中定义。 引用(强调我的):
如果左侧操作数的升级类型为int,则只有右侧操作数的五个最低位用作移位距离。 就好像右边的操作数受掩码值为0x1f(0b11111)的按位逻辑AND运算符&(第15.22.1节)。 实际使用的换档距离总是在0到31的范围内 。
因此,当你移动-3
,就好像你正在移动-3 & 0x1f
,这是29(只使用右侧操作数的五个最低位)。
a << -3
的结果是2^29 * a
; 对于a = 3
,这是1610612736
。 a >> -3
的结果是floor(a / 2^29)
; 对于a = 3
,这是0
。 请注意,当左操作数的升级类型long
且不是int
,使用的掩码值为0x3f
(仅使用右操作数的六个最低位)。
对于C#
从C#规范第7.9节 -
对于预定义的运算符,要移位的位数计算如下:
x
是int
或uint
,移位计数被的低位5个比特给出count
。 换句话说,移位计数从count & 0x1F
计算 x
的类型是long
或ulong
,移位计数由低位6位count
。 换句话说,移位计数从count & 0x3F
计算 这意味着转移的标志被忽略。 事实上,正如Jon Skeet在注释规范中指出的那样,由于规范定义的位掩码,以下代码将在i == 31
之后进行换行。
for (int i = 0; i < 40; i++)
{
Console.WriteLine(int.MaxValue >> i);
}
链接地址: http://www.djcxy.com/p/72503.html
上一篇: Behavior of bitwise shift operators when right operand is negative
下一篇: safe left shift