执行左移32位时出现意外输出

当我执行hex的左移时,我使用以下代码获得-1作为输出:

unsigned int i,j=0; i= (0xffffffff << (32-j)); printf("%d",i); 

类似地,当我将shift值更改为32时,输出为0,但我从编译器收到警告(left shift count >= width of type)

 unsigned int i,j=32; i= (0xffffffff << (32)); printf("%d",i); 

我希望在两种情况下(即0)都能得到相同的结果,但是为什么在#1情况下显示错误的输出而感到困惑,而在#2的情况下,结果是正确的,但编译器会发出警告!

结果在32位和64位x86机器中相同。

有人可以解释上面的结果吗?

对于32位整数,左对齐32或更高是未定义的行为。 这就是错误所在。

C11 6.5.7按位移位算子

对每个操作数执行整数提升。 结果的类型是提升的左操作数的类型。 如果右操作数的值为负或大于或等于提升的左操作数的宽度,则行为未定义。

将32位变量移位32会产生未定义的行为。

这是VS-2013编译器生成的程序集:

  int n = 0; mov dword ptr [n],0 int a = 0xFFFFFFFF << 32; mov dword ptr [a],0 int b = 0xFFFFFFFF << (32-n); mov ecx,20h sub ecx,dword ptr [n] or eax,0FFFFFFFFh shl eax,cl mov dword ptr [b],eax 

如您所见,事实上发生的事情是:

  • 当您移动常数值32时,编译器只需将结果设置为0
  • 当您通过变量(例如32-nn==0 )进行移位时,编译器使用shl

shl的实际结果取决于底层体系结构中此操作的实现。 在您的处理器上,它可能需要第二个操作数模32,因此第一个操作数移位0。

同样,上面的描述不是由标准规定的,因此它实际上取决于使用的编译器。