В 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
Решение
char
может быть подписанным или беззнаковым — это определяется реализацией.Вы видите эти результаты, потому что char
подписывается по умолчанию в вашем компиляторе.
Для знакового символа 0xFF соответствует −1 (так работает дополнение до двух).Когда вы пытаетесь переместить его, он сначала повышается до int
а затем сдвинули - вы фактически получите умножение на 256.
Итак, это код:
char c = 0xFF; // -1
int shifted = c << 8; //-256 (-1 * 256)
printf( "%d, %x", shifted, shifted );
Другие советы
Когда я впервые рассмотрел проблему, мое первоначальное мнение заключалось в том, что символ 'c' следует сдвинуть влево на 8 бит - все 8 бит отбрасываются, а пустой символ затем будет преобразован в целое число со значением 0.
Небольшое исследование показывает Обычные унарные преобразования - здесь для уменьшения большого количества арифметических типов преобразования применяются автоматически к операндам унарных операторов '!', '-', '~' и '*', и к каждому из операндов бинарных операторов '<<' и '>>'.
Поэтому символ 'c' преобразуется в int первый, затем сместился влево, дав ответ, который вы видите.
Ты узнаешь что-то новое каждый день!
c преобразуется в int до завершения операции сдвига.Предполагая, что ваша реализация по умолчанию подписывает символы, это означает, что вы получите 0xffffffff, который затем сдвигается влево, чтобы дать результат.
Если вы превратите c в беззнаковый символ, вы получите то, что ожидаете.
char — это не что иное, как подписанный символ.Таким образом, char c = 0xFF будет -1.Если вы оставите сдвиг -1 на 8 бит, вы получите -256.