如果char c = 0x80,为什么printf("%d \n",c << 1)输出-256?

Bri*_*Roy 5 c integer-promotion

#include<stdio.h>
int main(void)
{
  char c = 0x80;
  printf("%d\n", c << 1);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

-256在这种情况下输出.如果我写,c << 0那么输出是-128.

我不明白这段代码背后的逻辑.

Oli*_*rth 18

char可以在您的平台上签名,在这种情况下0x80代表-128(假设是两个补码).

当a char用作操作<<符的操作数时,它被提升为int(仍然是-128).所以当你应用左移时,你得到-256.从技术上讲,转移负值是实现定义的未定义,但您看到的是典型行为.


Jen*_*edt 6

您的出发点已经存在问题:

char c = 0x80;
Run Code Online (Sandbox Code Playgroud)

如果(看起来像你的情况)char是一个有符号的类型,你将整数常量赋给128一个只能保证最多值的类型127.然后,您的编译器可能会选择为您提供一些实现定义的值(-128在您猜测的情况下)或发出范围错误.

然后你正在对该负值进行左移.这给出了未定义的行为.总共有几个实现定义的选择加上确定结果的未定义行为:

  • 签字 char
  • 选择如何转换128signed char
  • 的宽度 char
  • 符号表示int(有三种可能性)
  • 如何实现(或不)左移的负面选择 int

查看所有这些案例可能是一个很好的练习,以了解不同的结果.

总结一些建议:

  • 选择一个适当的常量来初始化变量
  • 不要做普通算术 char
  • 不要对签名类型进行左移