-2

誰かが私が次の行動を理解するのを手伝ってくれませんか。

    1    #include <iostream>
    2
    3    using namespace std;
    4
    5    main()
    6    {
    7        uint32_t i = 32;
    8
    9        // cout << "(1<<32): " << (1<<32) << endl; // - This leads to a compilation error.
    10       cout << "(1<<32): " << (1<<i) << endl; // - This compiles and prints 1 - Why?
    11
    12        return 0;
    13    }

上記の行番号9のコメントを外すと、次のコンパイルエラーが表示されます(これは私にとって意味があります)

BitWiseLeftShift.c++: In function 'int main()':
BitWiseLeftShift.c++:9: warning: left shift count >= width of type

しかし、行番号10は私の質問です。正常にコンパイルされ、印刷されます

(1<<32): 1

循環ビットシフトのようなもの。なぜそれは1を印刷するのでしょうか?そして、私はそれを見てi == 33(1<<i)2を印刷します。

フォーラムを検索しましたが、関連する質問が見つかりませんでした。これが重複する質問である場合は、リンクを教えてください。


Railsクエリ]結合とインクルードの違い

@teachers = User.joins(:students).where("student_id IS NOT NULL")

上記は機能しますが、以下は機能しません。

@teachers = User.includes(:students).where("student_id IS NOT NULL")

私が理解している限り、結合とインクルードはどちらも同じ結果をもたらし、パフォーマンスが異なるはずです。これによるincludesと、Modelによって呼び出されたオブジェクトの関連レコードをロードするために使用します。ここでjoins、2つのテーブルを単純に追加します。を使用includesすると、を防ぐこともできますN+1 queries

最初の質問:コードの2行目が機能しないのはなぜですか?

2番目の質問:includes上記のような場合、誰かが常に使用する必要がありますか?

4

4 に答える 4

7

シフトは正当ではありませんが、コンパイラは最初のシフトのみをキャッチします。

6.5.7

整数昇格は各オペランドで実行されます。結果の型は、昇格された左オペランドの型です。右オペランドの値が負であるか、昇格した左オペランドの幅以上である場合、動作は未定義です。

于 2013-01-20T10:11:46.777 に答える
5

他の回答で指摘されているように、シフト量がシフトされたデータのビット単位のサイズより大きいか等しい場合 (または負の場合)、結果は未定義です。

ただし、あなたが見ている動作を説明するには -

一部のコンピューター アーキテクチャ (x86 を含む) では、シフト量がシフトされるデータのサイズのモジュロとして扱われるため、32 だけシフトすることは、まったくシフトしないことと同じです。別の言い方をすれば、上位ビットをマスクして下位ビットを使用するだけです。

于 2013-01-20T10:11:21.067 に答える
4

まず、これはエラーではなく、警告です。2 番目のケースでコンパイラが警告を出さない理由は、最初の割り当てから結果が未定義の動作になると推測するほど賢くない可能性があるためです。一方、最初のケースでは、32 ビットの定数左シフトは次のようになります。 「明らかに」コンパイラによってキャッチされる問題。

于 2013-01-20T10:12:37.087 に答える
1

定数シフトは、定数フォールディング中にプロプロセッサによって評価されますが、2番目のシフトは、ほとんどのコンパイラによって実行時に延期されます。これにより、コンパイラの連続パスによる異なる応答が説明されます。

静的解析を使用すると、両方が同じ結果になり、コンパイル中に検出できると判断できます。

于 2013-01-20T10:29:35.090 に答える