Опасности смещения чарса из области видимости - PullRequest
1 голос
/ 28 января 2020

Хорошо,

Я написал функцию, которая берет неподписанный символ из шестнадцатеричного файла и затем сдвигает его влево, чтобы уместить в WORD, DWORD или QWORD, как показано ниже:

retVal |= ((unsigned char)(memory[i]) << (8 * j));

(внутри al oop, отсюда переменные i и j).

Теперь visual studio напоминает мне о возможном переполнении арифметики.

Мой вопрос: если я ограничу j, то никогда больше чем 8 (размер uint64_t), я могу безопасно проигнорировать это сообщение? Я всегда немного раздражен предупреждениями и пытаюсь их устранить.

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

РЕДАКТИРОВАТЬ :

вот пример (это моя функция):

int getValuePNTR(const char* memory, int &start, int size)
{
    uint64_t retVal = 0;

    //now just add up array fields 
    for (int i = start + size-1,j = size-1; j >= 0; --j, i--)
    {
        //fprintf(stdout, "\ncycle: %d, memory: [%x]", j, memory[i]);

        if ((unsigned char)memory[i] == 00 && j > 0)
            retVal <<= 8;
        else
            retVal |= ((unsigned char)(memory[i]) << (8 * j));
    }
    //get the next field after this one
    start += size;
    return retVal;
}

1 Ответ

4 голосов
/ 28 января 2020

Вам нужно ограничить (8 * j), чтобы он был меньше sizeof(int) * CHAR_BIT, чтобы сохранить ваш код легальным во всех случаях (при условии стандартной реализации x86-64).

Во-первых, когда вы делаете (unsigned char)(memory[i]) << (8 * j) происходит целочисленное продвижение, а затем тип выражения является типом продвигаемой левой части. В этом случае unsigned char повышается до int, если sizeof(unsigned char) < sizeof(int) и unsigned int в противном случае.

Тогда [expr.shift] / 1 имеет

Поведение не определено, если правый операнд отрицательный или больше или равен ширине повышенного левого операнда.

По этой причине (8 * j) должно быть меньше sizeof(promoted_type) * CHAR_BIT

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...