Зависят ли операторы сдвига влево от размера регистра?

Пусть uint8 и uint16 будут типами данных для 8-битных и 16-битных положительных целых чисел.

uint8 a = 1;
uint16 b = a << 8;

Я протестировал эту программу на 32-битной архитектуре с результатом

b = 256

Будет ли та же программа в системе с регистрами длиной 8 бит давать результат:

b = 0 ?

потому что все биты в регистре сдвигаются в 0 на ‹‹ 8?


person Xvidia    schedule 23.06.2019    source источник
comment
Добро пожаловать в Stack Overflow. Какова ваша цель в смещении битов за пределы их размера? Это кажется немного необычным и может быть неопределенным поведением.   -  person Jonathon    schedule 23.06.2019
comment
Поведение зависит от размера типов данных. Целочисленные операнды повышаются до потенциально больших целых чисел при использовании в выражениях. Продвинутые размеры определяют поведение операций сдвига.   -  person Tom Karzes    schedule 23.06.2019


Ответы (2)


Регистры значения не имеют. Это о ширине ваших типов.

Когда вы сдвигаете значение на большее количество битов, чем оно имеет, поведение не определено. Компилятор, программа, компьютер, налоговая инспекция могут юридически оформить любые результаты соответственно. И нет, это не просто теория.

Однако операнды в C продвигаются до того, как будут сделаны интересные вещи. на них. Таким образом, ваш uint8_t становится int перед сдвигом влево.

Теперь то, что происходит, зависит от вашей архитектуры (определяемой конфигурацией вашего компилятора): является ли int в вашей реализации только 8-битным? Нет, это не так! В результате независимо от любого "размера регистра" должны соблюдаться правила языке, что дает математически правильный ответ (256). И даже если бы это было так, вы бы столкнулись с этим неопределенным поведением, поэтому вопрос был бы спорным.

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

person Lightness Races in Orbit    schedule 23.06.2019
comment
И int, и unsigned int гарантированно будут не менее 16 бит. - person klutt; 23.06.2019
comment
Это в основном правильно, по модулю двух приведенных выше комментариев. - person R.. GitHub STOP HELPING ICE; 23.06.2019

Будет ли та же программа в системе с 8-битными регистрами результатом b=0?

No.

В выражении a << 8 переменная a будет повышена до int перед битовым сдвигом. И int гарантированно будет не менее 16 бит.

b будет иметь значение 256 на всех платформах, если только в компиляторе нет ошибки.

Однако, если вы измените вторую строку на uint32 b = a << 16;, вы можете получить странные результаты. a по-прежнему будет повышен до int, но если int имеет длину два байта, то a << 16 вызовет неопределенное поведение.

person klutt    schedule 23.06.2019