シフトカウントが負または大きすぎるエラー - 正しい解決策は? 質問する

シフトカウントが負または大きすぎるエラー - 正しい解決策は? 質問する

ビッグエンディアンのクワッドワードを読み取るための次の関数があります (抽象基本ファイル I/O クラス内)。

unsigned long long File::readBigEndQuadWord(){
  unsigned long long qT = 0;
  qT |= readb() << 56;
  qT |= readb() << 48;
  qT |= readb() << 40;
  qT |= readb() << 32;
  qT |= readb() << 24;
  qT |= readb() << 16;
  qT |= readb() << 8;
  qT |= readb() << 0;
  return qT;
}

readb() 関数は BYTE を読み取ります。使用される typedef は次のとおりです。

typedef unsigned char   BYTE;
typedef unsigned short  WORD;
typedef unsigned long   DWORD;

問題は、シフト演算の最初の 4 行で 4 つのコンパイラ警告が表示されることです。

警告 C4293: '<<': シフト数が負または大きすぎるため、未定義の動作です

この警告が表示される理由は理解していますが、それを取り除く方法がわかりません。正しく次のようなことができます:

qT |= (unsigned long long)readb() << 56;

これで警告は消えますが、他に問題はないのでしょうか。BYTE は常に正しく拡張されるのでしょうか。おそらく私は考えすぎで、解決策はそれほど単純なのでしょう。皆さん、ここで私を助けてくれませんか。ありがとうございます。

ベストアンサー1

警告を削除する方法は正しいです。おそらくすでにご存知のとおり、警告はバイトの内容をワードの境界を超えてシフトしようとしているために発生します。それからそれをクワッドワードに格納します。この操作は未定義です。(値を割り当てる前に、割り当ての右側を評価します。) 最初に明示的にキャストすることで、シフトを行うのに十分なスペースが確保されるため、何も文句を言うことはありません。

おそらく、コンパイラはクワッドワードに格納することを理解できるはずなので、最初にクワッドワードを割り当ててそこでシフトを行うはずですが、それを理解できるほど賢く作られていない可能性があります。

また、これについてはよくわかりませんが、1 つの単語が 64 ビットであるため、これを x64 用にコンパイルしても警告は生成されない可能性があります。

おすすめ記事