直接将左移操作的结果分配给变量和C中的左移分配操作有什么区别?

时间:2017-05-30 06:40:16

标签: c bit-shift relational-operators

在下面的表达式中,左移操作的结果被赋值给变量i

int i;
i = 7 << 32;
printf("i = %d\n",i);

在下面的表达式中,执行左移位分配操作。

int x = 7;
x <<= 32;
printf("x = %d\n",x);

上述两种表达都给出了不同的结果。但是以下两个表达式并不相同。两者都给出了相同的结果。那么上述表达式返回不同值的原因是什么呢?

int a;
a = 1 + 1;
printf("a = %d\n",a);

int b = 1;
b += 1;
printf("b = %d\n",b);

3 个答案:

答案 0 :(得分:27)

C标准说:

  

如果右操作数为负数或更大,则结果为未定义   大于或等于左表达式类型中的位数。

因此,它是未定义的行为,因为int的大小通常为32位,这意味着只有031步骤才是的良好定义

答案 1 :(得分:5)

我同意Cody Gray's comments。对于将来会在这里结束的人来说,解决这种歧义的方法是使用unsigned long long。

unsigned long long int b = 7ULL<<32; // ULL here is important, as it tells the compiler that the number being shifted is more than 32bit.

unsigned long long int a = 7;
a <<=32;

答案 2 :(得分:1)

来自ISO/IEC 9899的抽象操作语义说:

6.5.7 Bitwise shift operators --- Semantics
  

3 ....如果值   右操作数是负数还是大于或等于   提升左操作数的宽度,行为未定义。

在你的情况下,反汇编并看到会发生什么,我们这样看:

[root@arch stub]# objdump -d a.out | sed '/ <main>/,/^$/ !d'
00000000004004f6 <main>:
  4004f6:       55                      push   %rbp
  4004f7:       48 89 e5                mov    %rsp,%rbp
  4004fa:       48 83 ec 10             sub    $0x10,%rsp
  4004fe:       c7 45 fc 07 00 00 00    movl   $0x7,-0x4(%rbp)
  400505:       b8 20 00 00 00          mov    $0x20,%eax
  40050a:       89 c1                   mov    %eax,%ecx
  40050c:       d3 65 fc                shll   %cl,-0x4(%rbp)  <<== HERE IS THE PROBLEM
  40050f:       8b 45 fc                mov    -0x4(%rbp),%eax
  400512:       89 c6                   mov    %eax,%esi
  400514:       bf b4 05 40 00          mov    $0x4005b4,%edi
  400519:       b8 00 00 00 00          mov    $0x0,%eax
  40051e:       e8 cd fe ff ff          callq  4003f0 <printf@plt>
  400523:       b8 00 00 00 00          mov    $0x0,%eax
  400528:       c9                      leaveq 
  400529:       c3                      retq   
  40052a:       66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

生成的代码确实尝试移位,但shll %cl,-0x4(%rbp)(向左移位)没有效果。

在这种情况下undefined behaviour位于汇编中,即在SHL操作中。