コンパイラのバックエンドが何をするかという観点から考えないことをお勧めします。最適化を使用していない場合は問題ではなく、最適化を使用している場合は、優れたコンパイラはわずかな命令で正しいことを行います。コンパイルターゲットに対して可能な限り。
それが言語で意味的に何を意味するかという観点から考えてください。たとえば、flags の型uint64_t
がBIT_NUMBER
31 より大きい場合、2 番目の形式のみが意図したとおりに動作する可能性があります。その理由は、おそらく 32 ビットである(BIT_MASK << BIT_NUMBER)
として評価され、ゼロに評価される 31 よりも大きいため、AND の後に全体がゼロになるためです。一方、64 ビット式として評価され (フラグは 64 ビットであるため)、AND を実行する前に適切にシフトされます。int
BIT_NUMBER
(flags >> BIT_NUMBER)
Clang コンパイラに関する興味深い話については、Clang: Defending C++ from Murphy's Million Monkeysを参照してください。これは、今日のコンパイラで可能なセマンティック理解の深さを示しています21:25
。 . これはトークで使用された例です
static const long long DiskCacheSize = 8 << 30; // 8 Gigs
Clang gives:
% clang++ -std=c++11 -fsyntax-only overflow.cpp
overflow.cpp:1:42: warning: signed shift result (0x200000000) requires 35
bits to represent, but 'int' only has 32 bits [-Wshift-overflow]
static const long long DiskCacheSize = 8 << 30; // 8 Gigs
~ ^ ~~
最近、gcc および Java JIT コンパイラーが、たとえば、シフト、マスク、および OR のグループが本質的に 32 ビット量の回転を行っていることを理解できるほど賢く、回転命令を生成することを知って驚きました。ビット単位のローテーションは、現在の Intel CPU のシフトよりも遅いですか? . 最近のコンパイラは非常に優れています。