私はちょうど答えました この質問 、forループで100億まで繰り返すのに、10億まで繰り返すよりもはるかに長い時間がかかる(OPは実際には10分後に中止した)理由を尋ねました:
for (i = 0; i < 10000000000; i++)
私や他の多くの人の明白な答えは、反復変数が32ビット(100億に達することはありません)であり、ループが無限ループになるためであるというものでした。
しかし、私はこの問題に気づきましたが、それでもコンパイラー内で実際に何が起こっているのか疑問に思います。
リテラルにはL
が追加されていないため、IMHOもint
型である必要があり、したがって32ビットである必要があります。したがって、オーバーフローのため、到達可能になるには範囲内の通常のint
である必要があります。 int
から到達できないことを実際に認識するために、コンパイラはそれが100億であることを認識し、したがって32ビットを超える定数と見なす必要があります。
そのようなリテラルは、L
が追加されていなくても、自動的にフィッティング(または少なくとも実装定義)範囲(この場合は少なくとも64ビット)にプロモートされますか?これは標準的な動作ですか?それとも、オーバーフローによるUB(整数オーバーフローは実際にはUB)のように、舞台裏で何か違うことが起こっていますか?標準からのいくつかの引用は、もしあれば、素晴らしいかもしれません。
元の質問はCでしたが、異なる場合はC++の回答にも感謝します。
C++に関する限り:
C++ 11、[Lex.icon]¶2
整数リテラルのタイプは、その値を表すことができる表6の対応するリストの最初のものです。
また、表6は、接尾辞と10進定数のないリテラルについて、次のように示しています。
int
long int
long long int
(興味深いことに、16進定数または8進定数の場合もunsigned
タイプが許可されますが、それぞれがafterリスト内の対応する符号付きのものになります)
したがって、その場合、定数がlong int
(または、long long int
が32ビットすぎる場合はlong int
)として解釈されていることは明らかです。
「リテラルが大きすぎる」とコンパイルエラーが発生することに注意してください。
プログラムの変換単位の1つに、許可されたタイプのいずれでも表現できない整数リテラルが含まれている場合、プログラムの形式が正しくありません。
(同上、¶3)
これはすぐにわかります このサンプルでは 、ideone.comが32ビットコンパイラを使用していることを思い出させます。
質問がCについてであることがわかりました...まあ、それは多かれ少なかれ同じです:
C99、§6.4.4.1
整数定数の型は、その値を表すことができる対応するリストの最初のものです。
c ++標準と同じリスト。
補遺:C99とC++ 11はどちらも、他のすべてが失敗した場合に、リテラルを「拡張整数型」(つまり、他の実装固有の整数型)にすることもできます。 (C++ 11、[Lex.icon]¶3; C99、§6.4.4.1¶5表の後)
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
コンパイラ内で実際に何が起こっているのかまだ疑問です
コンパイラがコードを解釈する方法に興味がある場合は、アセンブラを参照してください。
10000000000:
400054f:
mov -0x4(%rbp),%eax
mov %eax,-0x8(%rbp)
addl $0x1,-0x4(%rbp)
jmp 40054f <main+0xb>
したがって、10000000000を10000に置き換えると、無限ループにコンパイルされます。
....
test %al,%al
jne 400551