В C Сдвиг влево (char) 0xFF на 8 и отбрасывает его в int

В левом сдвиге (char) 0xff на 8 и отбрасывая его на int, получаем -256 или 0xffffff00. Может ли кто-нибудь объяснить, почему это должно произойти?

#include <stdio.h>
int main (void)
{   
    char c = 0xff;
    printf("%d %x\n", (int)(c<<8),(int)(c<<8));
    return 0;
}

Выход

-256 ffffff00

Ответ 1

char может быть подписан или без знака - он определен в соответствии с реализацией. Вы видите эти результаты, потому что char по умолчанию подписан вашим компилятором.

Для подписанного char 0xFF соответствует -1 (то, как работают два дополнения). Когда вы пытаетесь перенести его, сначала повышается до int, а затем сдвигается - вы фактически получаете умножение на 256.

Итак, вот этот код:

char c = 0xFF; // -1
int shifted = c << 8; //-256 (-1 * 256)
printf( "%d, %x", shifted, shifted );

Ответ 2

Когда я впервые рассмотрел проблему, мой первоначальный вид состоял в том, что char 'c' должен быть сдвинут влево на 8 бит - все 8 бит будут отброшены, пустой char затем будет передан в значение int 0.

Немного исследований показывает обычные Unary Conversions - это то, где можно уменьшить большое количество арифметических типов, конверсии применяются автоматически к операндам унарных операторов "!", "-", "~" и "*", и для каждого из операндов двоичного '< < и ' → '.

Поэтому char 'c' преобразуется в int сначала, затем сдвигается влево, давая ответ, который вы видите.

Вы узнаете что-то новое каждый день!

Ответ 3

c продвигается до int перед выполнением операции сдвига. Предполагая, что ваша реализация делает символы, подписанные по умолчанию, это означает, что вы получите 0xffffffff, который затем сдвигается влево, чтобы дать результат.

Если вы введете c в unsigned char, вы получите то, что ожидаете.

Ответ 4

char ничего не подписан char. Таким образом, char c = 0xFF будет -1. Когда вы оставили shift -1 на 8 бит, вы получите -256.