Можете ли вы объяснить это - "правила, включающие смешанные типы операндов, не применяются к операторам сдвига"
Я не могу понять строку "Результат сдвига имеет тот же тип, что и сдвинутая вещь (после интегральных повышений)" в следующем отрывке из книги С Майка Банахана (раздел 2.8.2.3).
Важно отметить, что правила, включающие смешанные типы операндов, не применяются к операторам сдвига. Результат сдвига имеет тот же тип, что и сдвинутая вещь (после интегральных повышений), и больше ни от чего не зависит.
Если что-то уже преобразуется в целое число (как требуется при использовании оператора сдвига), то как его можно преобразовать обратно в тот же тип, которым оно изначально было, если, конечно, оно не находится справа от присвоения и присваивается переменная того же типа, что и до целочисленного продвижения? Кроме того, что именно означает строка "правила, включающие смешанные типы операндов, не применяются к операторам сдвига"?
Пожалуйста, пролите свет на обе части вопроса. Спасибо.
Ниже приведены скриншоты из книги, касающиеся продвижения по службе при использовании побитовых операторов и при смешанных выражениях в целом, соответственно.
1 ответ
Это довольно просто; тип результата операции сдвига - это тип операнда LHS. Для большинства бинарных операторов результат основан на операндах LHS и RHS, но операторы сдвига отличаются.
unsigned char uc = 0x08;
unsigned short us = 0x0008;
unsigned int ui = 0x00000008;
unsigned long long ul = 0x0000000000000008;
(Я предполагаю, что sizeof(unsigned int) == 4
за этот ответ. Детали должны измениться, если они отличаются, но концепции остаются неизменными.)
Теперь рассмотрим некоторые выражения:
uc + uc;
Оба типа конвертируются в int
и результат int
,
us + us;
Опять же, оба типа преобразуются в int
и результат int
,
us + ui;
ui + us;
Значение в us
преобразуется в unsigned int
и результат unsigned int
(обратите внимание, что предыдущие значения были преобразованы в signed int
ака int
).
ui + ul;
ul + ui;
Оба эти выражения преобразовывают ui
для unsigned long long
и результат unsigned long long
, Обратите внимание, что эти выражения симметричны; тип результата (и, действительно, с +
оператор, значение результата) не зависит от того, какое значение находится на LHS, а какое от RHS оператора.
Так много для обычных операций; теперь как насчет смен?
uc << uc;
LHS преобразуется в int
обычными арифметическими преобразованиями и результатом является int
,
us << us;
Этот результат также является int
,
ui << ui;
Этот результат является unsigned int
,
ul << ul;
Этот результат является unsigned long long
, Но как насчет смешивания типов?
uc << ul; // Result: int
ul << uc; // Result: unsigned long long
us << ui; // Result: int
ui << us; // Result: unsigned int
ui << ul; // Result: unsigned int
ul << ui; // Result: unsigned long long
Продвинутый тип операнда LHS управляет типом результата. Для типов короче int
результат int
; для других типов тип - это тип операнда LHS.
Это все, что означает ваша цитата.