Des*_*tor 0 c# c++ java bit-shift bitwise-operators
在C&C++中,如果右操作数在使用>>和<<(右移和左移操作符)时为负,则程序的行为未定义.考虑以下计划:
#include <iostream>
int main()
{
int s(9);
std::cout<<(s<<-3);
}
Run Code Online (Sandbox Code Playgroud)
g ++给出以下警告:
[Warning] left shift count is negative [enabled by default]
Run Code Online (Sandbox Code Playgroud)
MSVS 2010发出以下警告:
warning c4293: '<<' : shift count negative or too big, undefined behavior
Run Code Online (Sandbox Code Playgroud)
现在我好奇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);
}
}
Run Code Online (Sandbox Code Playgroud)
计划成果:
1610612736
0
Run Code Online (Sandbox Code Playgroud)
C#轮到:
namespace left_shift_nagative
{
class Program
{
static void Main(string[] args)
{
int s = 3;
Console.WriteLine(s << -3);
Console.WriteLine(s >> -3);
}
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
1610612736
0
Run Code Online (Sandbox Code Playgroud)
1610612736的输出如何?这里发生了什么?Java语言规范(JLS)和C#语言规范或标准对此有何看法?在Java和C#中给出负移位计数时,<<和>>运算符如何工作?使用右移时如何输出0?我真的很困惑.
我将回答有关Java部分的内容(不能代表C#,但它可能是相同的).
移位运算符>>和<<在JLS定义部分15.19.引用(强调我的):
如果左侧操作数的提升类型是int,则只使用右侧操作数的五个最低位作为移位距离.就好像右手操作数受到按位逻辑AND运算符&(§15.22.1)和掩码值0x1f(0b11111)的影响.因此,实际使用的移位距离始终在0到31的范围内,包括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(仅使用右侧操作数的六个最低位).