Продвигаются ли целые типы при битовых сдвигах?

144
08 декабря 2019, 22:20

Мне известно, что малые типы продвигаются до int или unsigned int (зависит от реализации).

Меня интересует следующий вопрос.

Довольно часто вижу такой код:

uint8_t a, b, c, d;
// ...
uint32_t dword = (a << 24) | (b << 16) | (c << 8) | d;

Или такой:

uint8_t a, b;
// ...
uint16_t word = (a << 8) | b;

Верен ли этот код? Я сам считаю, что верен, потому что a, b, c и d должны продвигаться до int или unsigned int, поэтому величины не сдвигаются более, чем на ширину типа, и неопределенного поведения не возникает.

Answer 1

Согласно стандарту C++

7.3.6 Integral promotions [conv.prom]

1 A prvalue of an integer type other than bool, char16_t, char32_t, or wchar_t whose integer conversion rank (6.7.4) is less than the rank of int can be converted to a prvalue of type int if int can represent all the values of the source type; otherwise, the source prvalue can be converted to a prvalue of type unsigned int.

и

7.6.7 Shift operators [expr.shift]

1 The shift operators << and >> group left-to- right. The operands shall be of integral or unscoped enumeration type and integral promotions are performed. The type of the result is that of the promoted left operand. The behavior is undefined if the right operand is negative, or greater than or equal to the range exponent of the promoted left operand

и

7.6.12 Bitwise exclusive OR operator

1 The operands shall be of integral or unscoped enumeration type. The usual arithmetic conversions (7.4) are performed. Given the coefficients xi and > yi of the base-2 representation (6.7.1) of the converted operands x and y, the coefficient ri of the base-2 representation of the result r is 1 if either (but not both) of xi and yi are 1, and 0 otherwise. [Note: The result is the bitwise exclusive OR function of the operands. — end note]

Имейте в виду, что usual arithmetic conversions включают в себя integral promotions.

Таким образом в данном фрагменте кода

uint8_t a, b, c, d;
// ...
uint32_t dword = (a << 24) | (b << 16) | (c << 8) | d;

операнды a, b, c, d преобразуются к типу int перед выполнением операций.

READ ALSO
В чем различие инициализации richedit

В чем различие инициализации richedit

Появился вопрос, чем отличаются такие инициализации richedit:

122
Добавить к строке число в цикле

Добавить к строке число в цикле

Есть код который перебирает COM порты и если находит то подключается, если нет то ошибка

115
ошибка g++ &ldquo;undefined reference to &rdquo; [дубликат]

ошибка g++ “undefined reference to ” [дубликат]

Возникает ошибка при компиляции в g++Строки из Makefile:

144