Неожиданные результаты битового сдвига

Я инициализирую беззнаковое короткое целое с a = 0xff (все биты установлены). Затем я присваиваю b значению a>>7, что должно дать (0000 0001), и это так. Однако странно то, что когда я присваиваю c значению a‹‹7, это не эквивалентно (1000 0000). Я проверил это, выведя 0x80 (что равно 1000 0000) и c, но это не одно и то же.

Вот код:

unsigned short int a = 0xff;
unsigned short int b = a>>7;
unsigned short int c = a<<7; // c should == 0x80

Я не уверен, в чем проблема. Любая помощь приветствуется. Спасибо.

P.S. Под «выводом» я подразумеваю вывод 0x80 и c в десятичной и шестнадцатеричной форме.


person trikker    schedule 12.09.2009    source источник
comment
но что вы получаете, когда вы выводите c после присвоения a‹‹7 ?   -  person pavium    schedule 13.09.2009


Ответы (5)


короткий int имеет 16, а не только 8 бит.

Таким образом, вы, скорее всего, получите «0111 1111 1000 0000» в результате 0xff‹‹7.

person codymanix    schedule 12.09.2009
comment
Шорт может иметь 8 или 32 бита (даже другие размеры). int16_t и uint16_t — единственные типы C, для которых определено 16 бит. - person Dan Moulding; 13.09.2009
comment
Нет, short не может быть 8-битным. short должен иметь диапазон не менее -32767 до 32767, а unsigned short не менее 0 до 65535. Хотя 32 бита нормально. - person caf; 13.09.2009
comment
@Liran: Спасибо за ссылку. Я не знал о минимальном размере шорт. Общая идея, на которую я пытался указать, заключалась в распространенном заблуждении, что определенные типы имеют определенные фиксированные размеры. short == 16 бит - одно из таких заблуждений. - person Dan Moulding; 14.09.2009

Не угадывайте типы битов, используйте <stdint.h>


Короткое целое "обычно" имеет 16 бит. На самом деле, я почти уверен, что всегда их 16, за исключением тех марсианских компьютеров, но это не то, что обещает стандарт.

Если вы хотите объявить типы, которые имеют определенное количество битов, соответствующий метод:

#include <stdint.h>

  int8_t  a;
 uint8_t  b;
 int16_t  x;
uint16_t  y;

Это позволило бы избежать вашего не совсем правильного предположения о битовом представлении short. По какой-то причине Microsoft далеко не соответствует стандарту C99, даже в таких простых вещах, как <stdint.h>. К счастью, проект поддерживает стандартную версию VC++.

person DigitalRoss    schedule 12.09.2009

Я ожидаю, что вы получили 0x7f80. Я думаю, что вы хотели написать:

unsigned short int c =b<<7; // c should == 0x80

person Boojum    schedule 13.09.2009

К сожалению, VC++ (компилятор C) не имеет inttypes.h, поскольку он не полностью поддерживает C99. Вы должны использовать сторонние заголовки (например, stdint.h Пола Хси).

person Community    schedule 12.09.2009
comment
VС++ — это не компилятор C, это компилятор C++. Компиляторам C++ не обязательно поддерживать C99. В идеальном мире вы должны компилировать C с помощью компилятора C, а не компилятора C++, но мы, к сожалению, живем не в идеальном мире, поэтому иногда нам приходится использовать отбойный молоток, когда все, что нам нужно, это долото. - person Chris Lutz; 13.09.2009
comment
@Chris: Это может быть правдой в отношении Visual C++, но stdint.h может быть правильно реализован в 100% действительном C++. Он не требует каких-либо функций C99. Учитывая это и тот факт, что версии заголовка доступны для VC++, нет веских причин не использовать его. - person Dan Moulding; 13.09.2009
comment
VC является компилятором C, а также компилятором C++, однако это не компилятор C99. - person Michael Burr; 13.09.2009

Если вы хотите получить этот результат, вы можете отрезать часть a << 7 больше, чем 8-й наименее значащий бит, используя побитовое и:

unsigned short int c = (a << 7) & 0xff;
person caf    schedule 13.09.2009