C十六进制常数型

时间:2012-09-19 17:10:29

标签: c gcc

我写了以下c代码:

#include <stdio.h>

int main () {
  printf("%d\n", -1 >> 8);
  return 0;
}

我使用-m32标志在x86_64上使用gcc 4.6.3编译此代码。我按照我的预期打印出-1,使用二进制补码表示算术运算得到-1。

现在,如果我改为写

printf("%d\n", 0xFFFFFFFF >> 8);

我得到了16777215.我本来期望这个常量被解释为一个int(有符号),然后转换为算术,这将再次导致-1。我查看了最新的C标准,我似乎无法理解为什么会这样。有什么想法吗?

2 个答案:

答案 0 :(得分:13)

根据C99标准(6.4.4.1),十六进制常量将是此列表中可以表示它们的第一种类型:

int
unsigned int
long int
unsigned long int
long long int
unsigned long long int

十六进制文字0xFFFFFFFF不适合int(可以将值-0x80000000保存到0x7FFFFFFF),但适合unsigned int,因此它的类型将是未签名的。将无符号值0xFFFFFFFF右移8会产生16777215

答案 1 :(得分:10)

未修饰的整数文字具有不同的类型,具体取决于它们是否为十进制(C11中的6.4.4.1/5,C ++ 11中的表6):

  • 十进制文字,即[1-9][0-9]*,始终是签名的。

  • 十六进制和八进制文字是有符号或无符号的。如果有符号类型的值很大,但又小到足以适合相同宽度的无符号类型,则它将是无符号的。 (这是你的十六进制常数会发生的情况。)

右移负整数是实现定义的,你碰巧得到了符号扩展。右移无符号值可以简单地除以2。