2番目の例は有効ではないC99で、C++と似ています。おそらく、キャストが欲しい、つまり(int32_t)(a/UINT64_C(1000000000))
ですか?
a/UINT64_C(1000000000)
とa/1000000000
の間に違いはありますか?いいえ、彼らは同じ操作で終わるでしょう。しかし、私はそれが本当にあなたの質問だとは思わない。
あなたの質問は、整数リテラル "1000000000"の型はどうなるのでしょうか?それはint32_tかint64_tですか? C99の答えは、6.4.4.1段落5から得られます。
整数定数の型は、その値を表すことができる対応するリストの最初です。接尾辞なしの10進定数については
、リストはint
、long int
、long long int
です。したがって、最初のリテラルはほぼ確実にint
(int
のサイズに依存しますが、これはおそらく32ビットで10億を保持するのに十分な大きさです)。 UINT64_Cマクロの2番目のリテラルは、プラットフォームによってはunsigned long
またはunsigned long long
のいずれかになります。 uint64_t
に対応するどんなタイプでもなります。
したがって、定数の型は同じではありません。最初のものは署名され、2番目のものは署名されません。 2番目のコンパイラは、基本的なint型のコンパイラのサイズに応じて、より多くの「longs」を持つ可能性が高くなります。あなたの例では
、それは(a
はどのような場合にはリテラルと同等またはそれ以上のランクのものであろうので)/
オペレータがa
のタイプにリテラルを推進する必要がありますので、リテラルは、異なる種類を持っているという違いはありません。だから私はそれが本当にあなたの質問だとは思わなかったのです。
UINT64_C()
が重要な理由の例として、リテラルがより大きな型に昇格された場合に結果が変化する式を考えてみましょう。つまり、リテラルのネイティブタイプでオーバーフローが発生します。c
を計算するために
int32_t a = 10;
uint64_t b = 1000000000 * a; // overflows 32-bits
uint64_t c = UINT64_C(1000000000) * a; // constant is 64-bit, no overflow
、コンパイラはuint64_t
からa
を促進し、64ビットの乗算を実行する必要があります。しかし、b
を計算するには、両方の値が32ビットであるため、コンパイラは32ビット乗算を使用します。
uint64_t c = (uint_least64_t)(1000000000) * a;
また乗算は、少なくとも64ビットであることを強制する:最後の例で
は一つではなくマクロのキャストを使用することができます。
リテラルをキャストする代わりにマクロを使用するのはなぜですか? 1つの可能性は、小数のリテラルが署名されているためです。符号付きの値として表現できない定数が必要だとします。たとえば、
uint64_t x = (uint64_t)9888777666555444333; // warning, literal is too large
uint64_t y = UINT64_C(9888777666555444333); // works
uint64_t z = (uint64_t)(9888777666555444333U); // also works
プリプロセッサ式の可能性もあります。キャストは、#if
ディレクティブの表現に使用する正当な構文ではありません。しかし、UINTxx_C()
マクロはあります。
マクロはリテラルに貼り付けられた接尾辞を使用しているため、接尾辞はありません。UINT16_C(x)とUINT32_C(x)は同じである可能性があります。これにより、結果は(uint_least16_t)(65537) != UINT16_C(65537)
となります。誰かが期待するものではありません。
マクロUINTN_C(値)型uint_leastN_tに対応する整数定数式に展開されなければならない。実際、私はこれはC99§7.18.4.1に準拠していますどのように苦労を見ています。
質問を編集して既存の回答のポイントを無効にすることは好ましくありません。 –
また、「ジェネリックC」やC11規格ではなく、古いC99規格についてなぜ尋ねるのが不思議です。確かに、 ''と ''はC90には含まれていませんでしたが、C99はかなり古いものです。 –
@JonathanLeffler私は編集の問題を修正しました。私はANSI Cの後で最も広くサポートされている標準であり、私が使用しているものなので、C99について尋ねています。すべてのコンパイラがC11をサポートしていれば、世界はより良くなりますが、これはそうではありません... – user3368561