1. ホーム
  2. c#

負の値をチェックするのではなく、uintにキャストして範囲チェックを行う方が効率的ですか?

2023-08-18 20:39:22

質問

私は偶然、.NETの リスト ソース コード :

// Following trick can reduce the range check by one
if ((uint) index >= (uint)_size) {
  ThrowHelper.ThrowArgumentOutOfRangeException();
}

よりも効率的(?)らしい。 if (index < 0 || index >= _size)

このトリックの根拠が気になるところです。1 回の分岐命令は、2 回の uint ? あるいは、追加の数値比較よりもこのコードを高速化する他の最適化が行われているのでしょうか?

部屋の中の象に対処するために: はい、これはマイクロ最適化です、いいえ、私は私のコードでこれをどこでも使用するつもりはありません - 私はちょうど好奇心です;)

どのように解決するのですか?

から MSパーティションI の 12.1 節 (サポートされるデータ型) を参照してください。

符号付き整数型(int8、int16、int32、int64、ネイティブint)および対応する符号なし整数型(unsigned int8、unsigned int16、unsigned int32、native unsigned int64)。 整数型(int8、int16、int32、int64、ネイティブint)と、それに対応する符号なし整数型(符号なしint8、符号なしint16、符号なしint32、符号なしint64、ネイティブunsigned int)とでは,整数のビットの解釈の仕方が異なるだけである。符号なし整数が符号あり整数と異なる扱いを受ける演算では 符号なし整数が符号あり整数と異なる扱いを受ける場合(例えば,比較やオーバーフローを伴う演算など)には,整数を符号なし整数として扱う別の命令が用意されています。 整数を符号なしとして扱うための個別の命令があります(たとえば、cgt.un と add.ovf.un)。

つまり 変換 から int から uint は単に帳簿上の問題であり、今後、スタックやレジスタにある値は int ではなく unsigned int であることが知られています。

したがって、コードが JIT されると、2 つの変換は "free"になり、その後符号なし比較演算が実行されるようになるはずです。