Когда происходит неявное преобразование типов в C ++? - PullRequest
1 голос
/ 21 апреля 2019

Допустим, у нас есть следующий код, предназначенный для смещения битов a влево на i и замены i младших битов a на i старших битов b

unsigned short a;
unsigned short b;
auto i = 4;

a = (a << i) | (b >> (16 - i));

Это работает как ожидалось. Теперь давайте рассмотрим ситуацию, в которой мы хотим сделать это для пар разных типов. т.е. мы хотим сместить биты a влево на i и заменить i LSB a с i MSB b, за исключением того, что теперь у нас нет гарантии на размер a и b, только то, что они не подписаны. Рассмотрим случай, когда размер a меньше размера b

unsigned short a;
unsigned int b;
auto i = 4;

a = (a << i) | (b >> (32- i));

Я беспокоюсь о " превышении " a. Однако в зависимости от того, когда происходит повышение с a до unsigned int, значение может быть или не быть избыточным. Рассмотрим значение i=24. Это приведет к неопределенному поведению, если преобразование типов произойдет после сдвига, но не раньше. Таким образом, мой вопрос, когда преобразование типов в этом случае произойдет? Я полагаю, что мог бы явно привести a к большему типу, но я хотел бы избежать этого, если это возможно.

1 Ответ

1 голос
/ 21 апреля 2019

Вот соответствующая цитата из стандарта, [expr.shift / 1] :

[...] Операнды должны иметь целочисленный или незаданный тип перечисления, и выполняются интегральные преобразования. Тип результата - тип повышенного левого операнда. [...]

Это означает, что в вашем случае a будет повышен до int (или unsigned int) до того, как выполнит смену.

Обратите внимание, что в современных 32/64-битных компиляторах повышенный тип int, а не unsigned int. Продвигаемый тип - unsigned int, только если int не может представлять весь диапазон unsigned short (например, это верно для старых 16-разрядных компиляторов, где sizeof(int) равно 2 и sizeof(short)==sizeof(int)).

...