例から
unsigned long x = 12345678UL
コンパイラは、4バイト(32ビット)のメモリを設定するために、上記の例で「長い」だけを見る必要があることを常に学びました。問題は、L/ULが長いと宣言した後でも、L/ULを長い定数で使用する必要がある理由です。
接尾辞L
またはUL
が使用されない場合、コンパイラはリストの定数を含むことができる最初の型を使用します(C99標準の6.4.4:5節の詳細を参照してください。 10進定数、リストはint
、long int
、long long int
です。
その結果、ほとんどの場合、接尾辞を使用する必要はありません。プログラムの意味は変わりません。ほとんどのアーキテクチャでx
の初期化例の意味は変わりませんが、long long
として表現できない番号を選択した場合は変わります。接尾辞のU
部分が必要な例については、codebauerの回答も参照してください。
プログラマーが定数のタイプを明示的に設定したい場合があります。 1つの例は、可変長関数を使用する場合です。
printf("%lld", 1LL); // correct, because 1LL has type long long
printf("%lld", 1); // undefined behavior, because 1 has type int
接尾辞を使用する一般的な理由は、計算結果がオーバーフローしないようにすることです。 2つの例は次のとおりです。
long x = 10000L * 4096L;
unsigned long long y = 1ULL << 36;
両方の例で、接尾辞なしで、定数はint
型を持ち、計算はint
として行われます。各例では、オーバーフローのリスクが発生します。接尾辞を使用するということは、結果に対して十分な範囲がある代わりに、より大きな型で計算が行われることを意味します。
OrbitのLightness Racesが言うように、リタラルの接尾辞は割り当ての前にが付きます。上記の2つの例では、x
をlong
として宣言し、y
をunsigned long long
として宣言するだけでは、それらに割り当てられた式の計算のオーバーフローを防ぐのに十分ではありません。 。
別の例は、変数x
の型がint
である比較x < 12U
です。 U
接尾辞がない場合、コンパイラは12
をint
として入力するため、比較は符号付き整数の比較になります。
int x = -3;
printf("%d\n", x < 12); // prints 1 because it's true that -3 < 12
U
接尾辞を使用すると、比較は符号なし整数の比較になります。 「通常の算術変換」とは、-3が大きな符号なし整数に変換されることを意味します。
printf("%d\n", x < 12U); // prints 0 because (unsigned int)-3 is large
実際、定数の型は、「通常の算術変換」の仕組みのために、算術計算の結果を変更することさえあります。
10進定数の場合、C99によって提案された型のリストにはunsigned long long
が含まれないことに注意してください。 C90では、リストはその時点で最大の標準化された符号なし整数型(unsigned long
でした)で終了しました。その結果、標準タイプlong long
をC99に追加することで一部のプログラムの意味が変更されました。C90でunsigned long
と入力されたのと同じ定数は、符号付きlong long
代わりに。これが、C99でunsigned long long
を10進定数の型のリストに含めないことを決定した理由だと思います。例については、 this および this のブログ投稿を参照してください。
数値リテラルは典型的にはint型であるためです。 UL/Lは、コンパイラにint型ではないことを伝えます。 32ビット整数と64ビット長を想定
long i = 0xffff;
long j = 0xffffUL;
ここでは、右側の値を符号付きlongに変換する必要があります(32ビット-> 64ビット)
問題は、L/ULが長いと宣言した後でも、L/ULを長い定数で使用する必要がある理由です。
それは「後」ではないからです。それは「前」です。
最初に、リテラルがありますthenこれは、それを絞り込もうとしている変数の型に変換されます。
この投稿に関連するのは、u
の理由です。
u
の理由は、整数定数より大きいLLONG_MAX
は10進数形式です。
// Likely to generate a warning.
unsigned long long limit63bit = 18446744073709551615`; // 2^64 - 1
// OK
unsigned long long limit63bit = 18446744073709551615u`;