Правый сдвиг и целое число со знаком

В моем компиляторе следующий псевдо-код (значения заменены двоичным):

sint32 word = (10000000 00000000 00000000 00000000);
word >>= 16;

создает a word с битовым полем, который выглядит так:

(11111111 11111111 10000000 00000000)

Мой вопрос в том, могу ли я полагаться на это поведение для всех платформ и компиляторов С++?

Ответы

Ответ 1

Из следующей ссылки:
INT34-C. Не переносите выражение на отрицательное число бит или больше или равно количеству битов, которые существуют в операнде

Несоответствующий пример кода (правый сдвиг)
Результатом E1 >> E2 является E1 смещение по правому краю E2. Если E1 имеет неподписанный тип, или если E1 имеет подписанный тип и неотрицательное значение, значение результата является неотъемлемой частью частного E1/2 E2. Если E1 имеет подписанный тип и отрицательное значение, результирующее значение определяется реализацией и может быть либо арифметическим (подписанным) сдвигом:
Arithmetic (signed) shift
или логический (беззнаковый) сдвиг:
Logical (unsigned) shift
Этот несовместимый пример кода не может проверить, является ли правый операнд больше или равен ширине продвинутого левого операнда, позволяя поведение undefined.

unsigned int ui1;
unsigned int ui2;
unsigned int uresult;

/* Initialize ui1 and ui2 */

uresult = ui1 >> ui2;

Предположение о том, реализуется ли сдвиг вправо как арифметический (подписанный) сдвиг или логический (беззнаковый) сдвиг, также может привести к уязвимостям. См. Рекомендацию INT13-C. Используйте побитовые операторы только для неподписанных операндов.

Ответ 2

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

Ответ 3

В С++ нет. Это зависит от реализации и/или платформы.

В некоторых других языках да. Например, в Java оператор → точно определяется так, что он всегда заполняется левым самым битом (тем самым сохраняя знак). Оператор → > заполняется с использованием 0s. Поэтому, если вы хотите надежного поведения, одним из возможных вариантов будет переход на другой язык. (Хотя, очевидно, это может быть не вариант в зависимости от ваших обстоятельств.)

Ответ 4

Целые числа AFAIK могут быть представлены как знак-величина в С++, и в этом случае расширение знака будет заполняться 0s. Поэтому вы не можете полагаться на это.

Ответ 5

Из последней версии С++ 20:

Сдвиг вправо на целочисленных типах со знаком является арифметическим сдвигом вправо, который выполняет расширение знака.