无法理解C代码中的移位操作符行为

hai*_*img 5 c bit-shift

看看这个示例C代码(以一个测试用例为例):

main() {
  unsigned long a, b;
  int c;
  c = 32;
  a = 0xffffffff << 32;
  b = 0xffffffff << c;
  printf ("a=%x, b=%x\n", a, b);
}
Run Code Online (Sandbox Code Playgroud)

打印: a=0, b=ffffffff

我不明白为什么b不是零,就像一个.我在Microsoft C和GCC上测试了这个.

更新:我修复了愚蠢的错字(当然应该是<< c而不是<< b).但我的问题仍然存在,例如结果仍然相同.

Mys*_*ial 6

b在此处使用之前,您从未初始化为任何内容:

b = 0xffffffff << b;
Run Code Online (Sandbox Code Playgroud)

所以它可以是任何东西.(我想你实际上是想换班c.)


除此之外:

主要问题是,通过数据类型中的位数或更多位移位是未定义的行为.
所以如果文字0xffffffff是一个32位整数,那么这一行:

a = 0xffffffff << 32;
Run Code Online (Sandbox Code Playgroud)

没有标准定义.(看评论.)


您还应该收到编译器警告:

warning C4293: '<<' : shift count negative or too big, undefined behavior
Run Code Online (Sandbox Code Playgroud)


oua*_*uah 3

在 C 中,左移超过提升操作数的宽度是未定义的行为。

(C99,6.5.7p3)“如果右操作数的值为负或大于或等于提升的左操作数的宽度,则行为未定义。”

我假设在下面的示例中int类型unsigned int是 32 位。

无后缀的十六进制整数常量的类型是相应列表中可以表示其值的第一个:int, unsigned int, long, unsigned long, long long, unsigned long long

所以这里0xFFFFFFFF 是类型unsigned int并且0xFFFFFFFF << 32是未定义的行为。