2015-09-28 5 views
0

Is char c2=i1<<8>>24; действительный синтаксис C? (Где i1 is и unsigned integer) Кроме того, будет ли он давать результат сдвига i1 8 бит влево и 24 бита вправо соответственно? Я распаковываю char, ранее сохраненный в i1, вместе с тремя другими символами. Код ниже:Побитовый сдвиг влево и вправо в том же самом заявлении

unsigned char b3 = 202; 
unsigned char b2 = 254; 
unsigned char b1 = 186; 
unsigned char b0 = 190; 
... 


unsigned int i1=202; 
i1=i1<<8; 
i1=i1+254; 
i1=i1<<8; 
i1=i1+186; 
i1=i1<<8; 
i1=i1+190; 
... 

char c1=i1>>24; 
char c2=i1<<8>>24; 
+0

Ваше редактирование было полезно! можете ли вы опубликовать код, который объединяет 4 'char' в' int'? Тонкая ошибка может скрываться там. – chqrlie

+0

@chqrlie исправлено по запросу. – pmaurais

+0

Джон Боллинджер ударил быка! Вы должны определенно объявить 'c1',' c2' и т. Д. Как 'unsigned char'. Вы управляете байтовыми значениями, превышающими 127, вы просите проблему с ними обращаться с типом 'char', который может быть подписан по умолчанию. – chqrlie

ответ

7

Синтаксис в порядке (хотя трудно читать), и он будет разобран как c2 = (i1 << 8) >> 24.

Таким образом, он сдвинется влево i1 8 позиций, тем самым сдвинув крайние левые 8 бит от левого края, а затем сдвиньте правое положение 24 позиций, тем самым сдвинув крайние правые 16 бит с правого края. Если это то, чего вы хотели, тогда вы хороши. Я бы использовал круглые скобки, чтобы сделать его более читаемым.

Если вы только собираетесь конвертировать, что в char, это не очевидно, почему вы чувствуете необходимость, чтобы удалить биты высокого порядка (хотя это правда, что может быть архитектуры, в которой int и char одинаковы размер.)

Кроме того, как отметил Джон Боллинджер, это возможно конечный результат будет больше, чем может поместиться в char, которая не определена в общем случае, char является знаковым типом. (Это верно, даже если unsigned int - 32 бита, потому что вы технически не можете назначить значение, большее 127, для 8-разрядного символа со знаком.)

+1

Поскольку общий оператор присваивает результат переменной типа «char», может быть стоит отметить, что поведение присваивания не определено, если «char» является подписанным типом, а значение назначенного ему выражения больше, чем 'CHAR_MAX'. –

+1

@John Bollinger: не совсем неопределенное поведение, но определенно стоит упомянуть: * C11 6.3.1.3 p3 В противном случае новый тип подписан и значение не может быть представлено в нем; либо результат определяется реализацией, либо генерируется сигнал, определяемый реализацией. * – chqrlie

+0

@chqrlie, да, я был неаккуратным. Определено выполнение! = Undefined. В любом случае, лучше избегать. –

1

Да, это допустимый синтаксис. Это допустимый синтаксис также для подписанного int i1, и в этом случае вы можете достичь заполнения «верхней части» значения битом из выбранной позиции.

+4

Правое смещение подписанного int определяется реализацией, если значение отрицательное. Таким образом, вы не можете полагаться на расширение знака в переносном коде. – rici

1

Как уже отмечалось, это допустимый синтаксис. Вы можете добиться эффекта, который, по моему мнению, будет более понятным и портативным с:

unsigned char c2 = (i1 & 0xff0000) >> 16; 
+1

На самом деле это было бы более понятно: 'unsigned char c2 = (i1 >> 16) & 0xff;' – chqrlie

+0

@chqrlie Я не мог решить, что было более понятно, и я подумал, что было бы более понятно просто выбрать один , – Barmar

+0

«portably» готов к сдаче, так как код зависит от 32+ бит 'unsigned int', поскольку спецификация C только обязывает 16 бит или более. – chux

Смежные вопросы