Левый сдвиг и правый сдвиг на логическом

Я пытаюсь понять, как интегральное продвижение работает с операторами арифметических сдвигов. В частности, я хотел бы знать, какие значения a, b, c, d, e, f, g, h точно определены в соответствии со стандартом C++14, и какие из них могут зависеть от платформы / оборудования / компилятора (при условии, что sizeof(int) == 4).

int a = true << 3;
int b = true >> 3;

int c = true << 3U;
int d = true >> 3U;

int e = true << 31;
int f = true >> 31;

int g = true << 31U;
int h = true >> 31U;

2 ответа

Решение

От [expr.shift]:

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

Тип результата смещения bool всегда intнезависимо от того, что на правой стороне. Мы никогда не сдвигаемся, по крайней мере, на 32 или на отрицательное число, поэтому мы в порядке на всех счетах.

Для левых сдвигов (E1 << E2):

В противном случае, если E1 имеет тип со знаком и неотрицательное значение, а E1×2,E2 представляется в соответствующем типе без знака типа результата, тогда это значение, преобразованное в тип результата, является результирующим значением; в противном случае поведение не определено.

1 × 231 представлен unsigned intи это самая большая левая смена, которую мы делаем, так что у нас все хорошо.

Для сдвига вправо (E1 >> E2):

Если E1 имеет тип со знаком и отрицательное значение, результирующее значение определяется реализацией.

Е1 никогда не бывает отрицательным, так что у нас тоже все хорошо! Никакого неопределенного или определенного реализацией поведения нигде.

Ниже приводится в основном дополнение к ответу Барри, в котором четко объясняются правила смещения влево и вправо.

По крайней мере, для C++11 интегральное продвижение bool дает 0 для false и 1 для true: 4.5 Интегральные рекламные акции [conv.prom] § 6

Prvalue типа bool может быть преобразовано в prvalue типа int, где false становится равным нулю, а true становится единым.

Так что в оригинальных примерах b, d, f а также h все получит значение 0, a а также c оба получают 8 Значение: только совершенно определенное поведение до здесь.

Но e а также g получит значение без знака 0x80000000, поэтому было бы хорошо, если бы вы указали на переменную int без знака, но вы используете 32-битные целые числа со знаком. Таким образом, вы получаете интегральное преобразование: 4.7 Интегральное преобразование [conv.integral] §3

Если тип назначения подписан, значение не изменяется, если оно может быть представлено в типе назначения; в противном случае значение определяется реализацией.

И беззнаковое 0x80000000 не может быть представлено в 64-битном целом числе со знаком, так что результатом является реализация, определенная для e а также g,

Другие вопросы по тегам