C++ 默认情况下整型文字的类型不是int?
我刚才回答了这个问题,问为什么在for循环中迭代到100亿次要比迭代到10亿次花费更长的时间(OP实际上在10分钟后中止了它):C++ 默认情况下整型文字的类型不是int?,c++,c,overflow,literals,C++,C,Overflow,Literals,我刚才回答了这个问题,问为什么在for循环中迭代到100亿次要比迭代到10亿次花费更长的时间(OP实际上在10分钟后中止了它): for (i = 0; i < 10000000000; i++) (i=0;i < P>从我的标为ISO/IEC 9899的标准草案:TC2委员会草案- 2005年5月6日,规则与C++规则MaTeOo非常相似: 5整型常量的类型是可以表示其值的相应列表的第一个 我仍然想知道编译器内部到底发生了什么 如果您对编译器如何解释代码感兴趣,可以查看汇编程序 100
for (i = 0; i < 10000000000; i++)
(i=0;i<1000000000;i++)的
现在,我和其他许多人的明显答案是,这是因为迭代变量是32位的(永远不会达到100亿),循环得到一个无限循环
但是,尽管我意识到了这个问题,我仍然想知道编译器内部到底发生了什么
由于文本没有附加L
,因此它也应该是int
类型,因此是32位的。因此,由于溢出,它应该是一个正常的int
,在可到达的范围内。要真正认识到它不能从int
获得,编译器需要知道它是100亿,因此将它视为一个32位以上的常量
即使没有附加L
,这样的文本是否会自动提升到拟合(或至少实现定义的)范围(在本例中至少是64位),并且这是标准行为?或者是在幕后发生了一些不同的事情,比如UB由于溢出(整数溢出实际上是UB吗)?标准中的一些引用可能会很好,如果有的话
<>虽然原来的问题是C,但我也很欣赏C++的答案,如果有不同的话, 关于C++的: C++11,[lex.icon]^2 整型文字的类型是表6中对应列表的第一个,在表6中可以表示整型文字的值 对于不带后缀和小数常量的文字,表6给出了:
int
long int
long long int
(有趣的是,对于十六进制或八进制常量,也允许使用无符号
类型,但每个类型都位于列表中相应的有符号类型之后)
因此,很明显,在这种情况下,常数被解释为long int
(或者long long int
如果long int
太32位)
请注意,“文本太大”应导致编译错误:
如果程序的一个翻译单元包含不能由任何允许的类型表示的整数文本,则该程序是格式错误的
(ibidem,^3)
这一点很快就能看到,这提醒我们ideone.com使用32位编译器
我现在知道问题是关于C。。。嗯,差不多是一样的: C99,§6.4.4.1 整型常量的类型是可以表示其值的相应列表的第一个 <列表>与C++标准相同。
附录:C99和C++11都允许文本为“扩展整数类型”(即其他特定于实现的整数类型),如果其他所有操作都失败了。(C++ 11,[LX.ICON] 3;C99,损坏后4.4.4.1 5)表< < /P> < P>从我的标为ISO/IEC 9899的标准草案:TC2委员会草案- 2005年5月6日,规则与C++规则MaTeOo非常相似: 5整型常量的类型是可以表示其值的相应列表的第一个 我仍然想知道编译器内部到底发生了什么 如果您对编译器如何解释代码感兴趣,可以查看汇编程序 1000000000:
400054f:
mov -0x4(%rbp),%eax
mov %eax,-0x8(%rbp)
addl $0x1,-0x4(%rbp)
jmp 40054f <main+0xb>
简短版本:是的,编译器自动提升文本,尽管我不确定这是“每个人都这样做”还是“它是必需的”。此外,是的,有符号整数溢出实际上是UB。我把它留给其他人去挖掘标准引用并堆积奖励。什么类型的变量是“I”?@Jim由于OP的问题及其解决方案,它是一个32位的变量,我自己猜它是一个
int
或无符号int
(符号性在这里真的很重要吗?)。任何时候你在引用语言规则时使用“IMHO”,这表明你应该先检查标准。@KeithThompson事实上我应该先研究标准,而不是像这样懒散地问问题。你可能会责怪我太懒了。啊,那么我经常看到和使用的L
后缀就没有那么必要了?也许只有当你想完全明确地描述类型的时候。顺便问一下,这些引用(如LX.ICON)意味着什么,它们是放置持有者还是破坏了它们?”克里斯:这是C++标准中的一部分,它们只是被标记为这样。C也可以看到@克里斯蒂娜:我也像你一样思考,然后检查标准来回答你的问题。L
后缀在值小到足以容纳int
时非常有用,但您希望它是long
类型:42L
是long
类型。示例:60*60*24
为86400,如果int
为16位,则可能溢出60L*60L*24L
不会溢出。Matteo也提到了C标准的类似行为,不过还是要感谢您提供了这个详细的列表。我甚至不知道有一个LL
后缀(但它是有意义的)。我还猜他把它做成了一个无限循环,但我不知道他是用什么权利这样做的。但无论如何,还是要感谢汇编程序。如果您使用gcc和-Wextra,也可以部分解释原因。它应该说,由于数据范围有限,比较总是正确的type@user1034749:这就是为什么最好始终使用-Wall-Wextra
运行gcc
。
400054f:
mov -0x4(%rbp),%eax
mov %eax,-0x8(%rbp)
addl $0x1,-0x4(%rbp)
jmp 40054f <main+0xb>
....
test %al,%al
jne 400551