整数文字的类型默认不是int?

时间:2011-11-13 00:24:41

标签: c++ c overflow literals

我刚刚回答this question,其中提到为什么迭代直到for循环中的100亿需要更长时间(OP实际上在10分钟后中止)而不是迭代直到10亿:

for (i = 0; i < 10000000000; i++)

现在我和其他许多人明显的回答是,这是因为迭代变量是32位(永远不会达到100亿)并且循环得到无限循环。

但是虽然我意识到了这个问题,但我仍然想知道编译器内部究竟发生了什么?

由于文字没有附加L,因此IMHO也应该是int类型,因此也是32位。因此,由于溢出,它应该是可以到达的范围内的正常int。要真正认识到无法从int到达它,编译器需要知道它是100亿,因此将其视为超过32位的常量。

这样的文字是否会自动升级到拟合(或至少是实现定义的)范围(在这种情况下至少是64位),即使没有附加L并且这是标准行为?或者是在幕后发生了什么不同,比如UB由于溢出(整数溢出实际上是UB)?标准中的一些引用可能很好,如果有的话。

虽然最初的问题是C,但我也很欣赏C ++的答案,如果有的话。

3 个答案:

答案 0 :(得分:34)

就C ++而言:

C ++ 11,[lex.icon]¶2

  

整数文字的类型是表6中第一个可以表示其值的列表。

表6中,对于没有后缀和小数常量的文字,给出了:

int
long int
long long int

(有趣的是,对于十六进制或八进制常量,也允许unsigned类型 - 但每个列表中相应的签名后

因此,很明显,在这种情况下,常量被解释为long int(如果long long int太32位,则为long int

请注意,“太大的文字”会导致编译错误:

  

如果某个程序的翻译单元中包含一个无法用任何允许类型表示的整数文字,则该程序格式不正确。

(ibidem,¶3)

及时看到in this sample,提醒我们ideone.com使用32位编译器。


我现在看到问题是关于C ......好吧,它或多或少是相同的:

C99,§6.4.4.1

  

整数常量的类型是相应列表中可以表示其值的第一个。

列表与C ++标准中的列表相同。


附录:如果其他所有内容都失败,C99和C ++ 11也允许文字为“扩展整数类型”(即其他特定于实现的整数类型)。 (C ++ 11,[lex.icon]¶3; C99,§6.4.4.1¶5表后)

答案 1 :(得分:10)

根据标准 ISO / IEC 9899:TC2委员会草案 - 2005年5月6日的C标准草案,规则与Matteo发现的C ++规则非常相似:

  

5整数常量的类型是相应列表中可以表示其值的第一个。

Suffix      Decimal Constant          Octal or Hexadecimal Constant
-------------------------------------------------------------------
none        int                       int
            long int                  unsigned int
            long long int             long int
                                      unsigned long int
                                      long long int
                                      unsigned long long int

u or U      unsigned int              unsigned int
            unsigned long int         unsigned long int
            unsigned long long int    unsigned long long int

l or L      long int                  long int
            long long int             unsigned long int
                                      long long int
                                      unsigned long long int
Both u or U unsigned long int         unsigned long int
and l or L  unsigned long long int    unsigned long long int

ll or LL    long long int             long long int
                                      unsigned long long int

Both u or U unsigned long long int    unsigned long long int
and ll or LL 

答案 2 :(得分:1)

  

我仍然想知道编译器里面究竟发生了什么。

如果您对编译器如何解释代码感兴趣,可以查看汇编程序。

百亿:

400054f:
mov    -0x4(%rbp),%eax
mov    %eax,-0x8(%rbp)
addl   $0x1,-0x4(%rbp)
jmp    40054f <main+0xb>

所以它只是把它编译成无限循环, 如果用10000代替10000000000:

....
test   %al,%al
jne    400551