Сдвиг отрицательный или слишком большая ошибка - правильное решение? - PullRequest
19 голосов
/ 11 июня 2010

У меня есть следующая функция для чтения четырехзначного слова с прямым порядком байтов (в абстрактном базовом файле ввода-вывода):

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 () считывают байты. Вот используемые определения типов:

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

Дело в том, что я получаю 4 предупреждения компилятора в первых четырех строках с помощью операции shift:

предупреждение C4293: «<<»: число смен отрицательный или слишком большой, неопределенный поведение </p>

Я понимаю, почему возникает это предупреждение, но я не могу понять, как от него избавиться правильно . Я мог бы сделать что-то вроде:

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

Это удаляет предупреждение, но нет ли другой проблемы, будет ли БАЙТ правильно все время расширяться? Может быть, я просто слишком много думаю об этом, и решение так просто. Можете ли вы, ребята, помочь мне здесь? Благодаря.

Ответы [ 2 ]

15 голосов
/ 11 июня 2010

Ваш способ удаления предупреждения правильный. Как вы, вероятно, уже знаете, предупреждение появляется, потому что вы пытаетесь переместить содержимое байта за границы слова, , а затем сохранить его в четырех словах. Эта операция не определена. (Он будет оценивать правую часть присваивания перед присваиванием значения.) При явном приведении вначале теперь достаточно места для выполнения сдвига, поэтому не к чему придраться.

Возможно, компилятор должен быть в состоянии выяснить, собираетесь ли вы хранить его в четырех словах, поэтому он должен сначала выделить четырехсловое слово и выполнить там сдвиг, но, возможно, он не был сделан достаточно умным, чтобы понять это. .

Кроме того, я не уверен в этом, но, возможно, компиляция этого для x64 также не выдаст предупреждение, так как одно слово составляет 64 бита?

2 голосов
/ 08 июля 2015

qT | = (длинная строка без знака) readb () << (shiftvalue & 63);Это будет идеальное решение при условии, что вам не требуется сдвиг более 63 бит </p>

...