3

次の計算結果は「1」です。

unsigned long iEndFrame = ((4294966336 + 1920 - 1) / 1920) + 1;

誰かが理由を見ますか?これなら対応できると思いunsigned longました。

助けてくれてありがとう。

4

3 に答える 3

14

計算の右側の値のタイプはunsigned intorintです。

4294966336 + 1920 = 4294968256

と仮定sizeof(unsigned int) == 4すると、これはオーバーフローし、960

(960-1)/1920 = 0

(整数演算での丸めのため)。これにより、

0 + 1 = 1

より大きな型を使用して計算を実行する場合 (および を想定sizeof(unsigned long) > sizeof(unsigned int))、計算内でキャストする必要があります。

unsigned long iEndFrame = (((unsigned long)4294966336 + 1920 - 1) / 1920) + 1;

または、Slavaが指摘したように、リテラル値の1つをサフィックスunsigned longを使用して型に設定しますUL

unsigned long iEndFrame = ((4294966336UL + 1920 - 1) / 1920) + 1;
于 2013-10-15T21:08:37.620 に答える
3

「unsigned long でこれを処理できると思いました。」- これが何を意味するのかわかりません。評価する式には、 を使用する必要があることを示唆するものは何もありませんunsigned long。最終的にunsigned long変数を初期化しても、評価のプロセスには影響しません。初期化式はそれとは完全に独立して処理されます。

現在、C++ 言語では、サフィックスのない 10 進整数リテラルには常に符号付きの型があります。コンパイラは、式で使用されるリテラルに対して符号なしの型を選択することはできません。コンパイラは、リテラルの値に応じてintlong intまたはlong long int(最後のもの - C++11) を使用する必要があります。コンパイラは、実装依存の拡張整数型を使用できますが、それらが署名されている場合に限ります。また、すべての符号付き型が小さすぎると、プログラムの動作が未定義になります。

「従来の」16、32、または 64 ビット幅の整数型を持つ典型的な実際のプラットフォームで作業していると仮定すると、ここには 2 つの可能性しかありません。

  • プラットフォーム上ですべての符号付き整数型が小さすぎて表現できない4294966336場合、プログラムは未定義の動作をします。話の終わり。

  • 少なくとも 1 つの符号付き整数型が に対して十分な大きさ4294966336である場合、評価のオーバーフローは発生せず、式は と評価され2236963ます。

したがって、その結果についての唯一の実際の言語レベルの説明は、1未定義の動作に遭遇しているということです。これは、すべての符号付き型が小さすぎて、式で使用したリテラルを表すことができないためです。

お使いのプラットフォームで、符号付き整数型が実際に表現するのに十分な大きさ4294966336(つまり、少なくとも 64 ビットの型がある) である場合、その結果は、コンパイラが壊れているという事実によってのみ説明できます。

PSunsigned int評価に使用される可能性があるのは、古い C 言語 - C89/90 のみであることに注意してください。これにより、得られた結果の 3 番目の説明が生成されます。しかし、繰り返しになりますが、その説明は C89/90 コンパイラにのみ適用され、C++ コンパイラや C99 コンパイラには適用されません。あなたの質問には [C++] というタグが付けられています。

于 2013-10-15T21:32:13.590 に答える
1

これをコメントとして残すつもりでしたが、十分な評判がありません。とにかくこれを共有したかったのは、tmighty の質問には 2 つの要素があり、そのうちの 1 つは正確に答えられない可能性があるためです。

  • まず、使用しているデータ型について明示する必要があります。つまり、UL などの接尾辞または明示的な型変換を使用します。他の答えはこれを十分に明確にしていると思います。
  • 次に、十分な大きさのデータ型を選択する必要があります。

あなたはすでに「unsigned longでこれを処理できると思った」と述べており、他の回答はこれを確認しているようですが、私が知っていることから-そして確認するために今すぐ再確認してください-unsigned long十分な大きさではない可能性があります. 少なくとも4294967295であることが保証されていますが、これはユース ケースには小さすぎます。具体的には、VC++ を使用して Windows でチェックしたところ、32 ビットと 64 ビットの両方のコンパイルで ULONG_MAX が と定義されています4294967295

代わりに、「ULL」サフィックスを使用して を使用する必要がある場合があります。unsigned long longその最大値は少なくとも18446744073709551615. 目的に十分な大きさであると定義されているプラ​​ットフォームがあったとしても、unsigned long十分な大きさであることが実際に保証されているデータ型を使用したい場合があると思います。

于 2013-10-15T22:37:42.470 に答える