【问题标题】:Is the integer constant's default type signed or unsigned?整数常量的默认类型是有符号还是无符号?
【发布时间】:2012-07-03 12:01:41
【问题描述】:

整数常量的默认类型是有符号还是无符号?比如0x80000000,我该如何决定是用它作为有符号整数常量还是无符号整数常量而不带任何后缀?

如果是有符号整数常量,下面的情况如何解释?

printf("0x80000000>>3 : %x\n", 0x80000000>>3);

输出:

0x80000000>>3 : 10000000

以下情况可以表明我的平台使用算术位移,而不是逻辑位移:

int n = 0x80000000;

printf("n>>3: %x\n", n>>3);

输出:

n>>3: f0000000

【问题讨论】:

  • 通常0x80000000INT_MAX + 1,所以它是无符号的。因此,第一个示例中的逻辑移位。但是当您将其分配给int 时,您会调用未定义的行为,并且通常结果是INT_MIN。左移负整数是实现定义的,通常使用算术移位。不同之处在于,在后者中,您将其强制为有符号类型。
  • @DanielFischer INT_MAX + 1 是 UB,但 int n = 0x80000000; 不是 UB,而是实现定义的,在这种情况下,整数转换由 6.3.1.3p3(在 C99 中)控制
  • @ouah INT_MAX + 1 是一个数学表达式,而不是 C。但是,将其转换为 int 不是未定义的行为,而是实现定义的,这是正确的。我的错。

标签: c


【解决方案1】:

C 对十进制、八进制和十六进制常量有不同的规则。

对于十进制,它是值可以适合的第一种类型:intlonglong long

对于十六进制,它是值可以适合的第一个类型:intunsigned intlongunsigned longlong longunsigned long long

例如在具有32-bit intunsigned int 的系统上:0x80000000unsigned int

请注意,对于十进制常量,C90 有不同的规则(但对于十六进制常量规则没有改变)。

【讨论】:

  • 迄今为止唯一正确的答案。 (Nits:您没有为八进制指定规则 [参见 hex],从 C90 开始,十六进制文字通过添加 long long 类型而改变)。
  • 但是我们不能期待int n = 0x80000000; 中的警告,因为它正在将 uint32_t 分配给 int32_t 并以某种方式溢出?
  • 这是否意味着语句“像 1234 这样的整数常量是一个 int。” [K&R2] 中的错误?
  • @VictorS:不,它是正确的 - 1234 在int 的保证最小范围内,因此它始终具有int 类型。
  • @mbonnin 一些编译器可以显示警告,但标准不需要警告。任何算术类型到任何算术类型之间都有隐式转换。
【解决方案2】:

它是有符号的如果它适合一个有符号整数。要使其无符号,请附加 u 后缀,例如1234u.

您可以将有符号值转换为无符号,方法是将其分配给无符号变量。

unsigned int i = 1234u; // no conversion needed
unsigned int i = 1234;  // signed value 1234 now converted to unsigned

对于 0x80000000,如果 int 在您的平台上是 32 位,它将是 无符号,因为它不适合带符号的 int。


另外需要注意的是,右移的行为取决于平台。在某些平台上,它是符号保留(算术),而在某些平台上,它是一个简单的按位移位(逻辑)。

【讨论】:

  • 已更新以回答您的其他问题。
  • 0x80000000 在 32 位和 64 位系统上未签名但未签名。
  • 如果它适合有符号整数,则它是有符号的我认为这种说法是错误的。
  • 十进制整数常量总是有符号的。对于十六进制常量,它可以适合long,但如果适合unsigned int,它将是unsigned int。有符号整数不是有符号int 的同义词。 long 类型也是有符号整数类型。
  • 转换会发生什么??从已签名到未签名?
猜你喜欢
  • 2010-12-06
  • 2022-01-03
  • 2010-09-09
  • 1970-01-01
  • 2019-09-10
  • 2015-04-22
相关资源
最近更新 更多