3

私は 64 ビット (一部の計算用) と 32 ビット (省スペース ストレージ用) の符号なし整数を混合するプログラムに取り組んでいるので、オーバーフローを避けるために演算中にそれらを整理しておくことが非常に重要です。

これが問題の例です

unsigned long n だけ 1 を左にビット シフトしたいのですが、結果を unsigned long long にしたいのです。これは if ステートメントの比較操作で使用されるため、代入は行われません。コードをいくつか紹介します。

void example(unsigned long shift, unsigned long long compare)
{
    if((1<<shift)>compare)
    {
        do_stuff;
    }
}

私はこれが私が望むことをしないと思うので、次は私が望むことをしますか?

void example(unsigned long shift, unsigned long long compare)
{
    if(((unsigned long long)1<<shift)>compare)
    {
        do_stuff;
    }
}

これらのビット幅を細かく管理するにはどうすればよいですか? 演算が実行されるビット幅を決定するのはどちらのオペランドですか、それとも 2 つのうち大きい方ですか?

また、可能であれば、 + * / % などの他の操作でもこれがどのように機能するかを概説したいと思います.

おそらく、この情報を含むリソースへの参照は良いでしょう。この情報の明確な記述はどこにも見つからないようです。あるいは、投稿するだけの単純なルールかもしれません。私はわかりません。

4

3 に答える 3

4

それはまさにあなたが望むことをします。ただし、これは (この特定のケースでは) type のリテラル定数を使用するだけで実現できますlong long1LL

于 2012-10-01T00:37:33.050 に答える
4

演算が実行されるビット幅を決定するのはどちらのオペランドですか、それとも 2 つのうち大きい方ですか?

ビットシフトの場合、操作が実行されるタイプを決定するのは左オペランド (シフトされるもの) です。整数昇格によってintorに変換された場合unsigned int、演算はその型で実行されます。それ以外の場合は、左側のオペランドの型で実行されます。

比較のために、シフトの結果を他のオペランドの型に変換することができます。コード例では、整数定数の1type が typeintであるため、シフトは type で実行され、その結果は比較のためにintに変換されます。unsigned long long接尾辞付きのliteralを使用する場合と同様に、結果の型は整数の昇格によって変更されないため、キャストは機能します1ull

リストされている他の演算、算術演算 (比較など) の場合、演算が実行される型は、次のように両方のオペランドによって決定されます。

それ以外の場合、両方のオペランドで整数昇格が実行されます。次に、プロモートされたオペランドに次の規則が適用されます。

  • 両方のオペランドが同じ型の場合、それ以上の変換は必要ありません。
  • それ以外の場合、両方のオペランドが符号付き整数型であるか、両方が符号なし整数型である場合、整数変換ランクの小さい型のオペランドは、ランクの大きいオペランドの型に変換されます。
  • それ以外の場合、符号なし整数型のオペランドのランクが他のオペランドの型のランク以上である場合、符号付き整数型のオペランドは符号なし整数型のオペランドの型に変換されます。
  • それ以外の場合、符号付き整数型のオペランドの型が符号なし整数型のオペランドの型のすべての値を表すことができる場合、符号なし整数型のオペランドは符号付き整数型のオペランドの型に変換されます。
  • それ以外の場合、両方のオペランドは、符号付き整数型のオペランドの型に対応する符号なし整数型に変換されます。
于 2012-10-01T00:48:58.747 に答える
3

必要なのはlong long リテラルです。これを行うには、1LL代わりに を使用し1ます。

于 2012-10-01T00:35:49.907 に答える