我刚刚回答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 ++的答案,如果有的话。
答案 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