C位操作的行为

C位操作的行为,c,bit-manipulation,C,Bit Manipulation,我目前正在C中试验逐位运算,我试图理解为什么这段代码为变量a和变量b打印不同的值。 我知道一个32位的移位会溢出正常整数的1变量,但我的理解是在这两种情况下它都应该打印0 相反,它打印的似乎是一个带有无符号int a的随机数和一个带有无符号long int b的0值 我错过了什么 编辑 现在我只尝试使用31位移位,编译器没有给我任何警告。 资料来源: 它输出18446744071562067968,这真的不是2^31。有什么线索吗?您的代码在12.04LTS上的gcc 4.6.3中的运行情况与我

我目前正在C中试验逐位运算,我试图理解为什么这段代码为变量a和变量b打印不同的值。 我知道一个32位的移位会溢出正常整数的1变量,但我的理解是在这两种情况下它都应该打印0

相反,它打印的似乎是一个带有无符号int a的随机数和一个带有无符号long int b的0值

我错过了什么

编辑

现在我只尝试使用31位移位,编译器没有给我任何警告。 资料来源:


它输出18446744071562067968,这真的不是2^31。有什么线索吗?

您的代码在12.04LTS上的gcc 4.6.3中的运行情况与我预期的一样。但它会产生几个关于移位计数大于类型宽度的警告

汇编结果如下:

测试c:在函数“main”中:

Test.c:5:5:警告:左移位计数>=类型的宽度[默认启用]

Test.c:6:4:警告:左移位计数>=类型的宽度[默认启用]

运行的输出:

4.8

0 0

祝你好运

第一个a是随机的,因为移位计数大于类型的长度。这是未定义的行为:

/tmp/test.c: In function 'main':
/tmp/test.c:5:6: warning: left shift count >= width of type [enabled by default]
      unsigned int a = 1 << 32;
      ^
b的正确表达式为:

unsigned long int b = 1L << 32;
编辑以回答您的新问题:


在C中,1在默认情况下是带符号的int,因此1如下更改代码

#include <stdio.h>

int main(){
  int shift = 31;
  unsigned long int b = 1LU << shift; /* or 1U << shift */
  printf("%lu\n", b);
  return 0;
}
在您的系统上,long int似乎是64位的

您得到的int结果是负数,并试图将其存储到64位无符号中,从而得到奇怪的数字


p、 s.18446744071562067968=ffffffff8000000

如果是。好的,但为什么它在两个操作之间给出不同的结果?表达还是一样的:1因为鼻魔。嗯。。。你从哪里得到了一个可以产生sizeoflong int==8的编译器?另请看:如果我将b的声明更改为unsigned long int b=1L,因为4294967296是0b100000000000000,那么你很好:@ShafikYaghmour感谢你的专家评论。你能解释一下为什么它没有定义吗?我从你那里读过很多知识分享的帖子。这里的简短评论/解释对OP和我都有好处。你对问题的解释不完整,我在我的文章中链接了一个解释。您的示例代码是正常的,因为您只移动了31次,但您需要解释未定义行为的结果是不可靠的,尽管它们可以在特定实例上解释,但这不是一般性的解释。请注意,clang为OPs代码生成了一些有用的错误消息,请使用以下标志查看a:-Wall-Wextra-Wconversion-pedantic-fsanitize=未定义。在我阅读问题时,OP理解了问题中的问题并编辑了问题。我只回答了编辑过的部分。你说这仍然是未定义的行为。我试过了,但它没有显示警告。或者我错过了你想要传达的东西。
/tmp/test.c: In function 'main':
/tmp/test.c:5:6: warning: left shift count >= width of type [enabled by default]
      unsigned int a = 1 << 32;
      ^
/tmp/test.c:6:8: warning: left shift count >= width of type [enabled by default]
      unsigned long int b = 1 << 32;
      ^
unsigned long int b = 1L << 32;
#include <stdio.h>

int main(){
  int shift = 31;
  unsigned long int b = 1LU << shift; /* or 1U << shift */
  printf("%lu\n", b);
  return 0;
}