2013-12-03 3 views
5

В настоящее время я до главы 2 на языке программирования C (K & R) и чтения о побитовых операциях.Преобразование типов: подписанный int до unsigned long in C

Это пример того, что вызвало мое любопытство:

x = x & ~077 

Если предположить, что 16-битная длина слова и 32-разрядное типа, что я думаю, что произойдет это 077 будет первым быть преобразованы в:

0000 0000 0011 1111 (16 bit signed int). 

Это позволило бы дополнить до:

1111 1111 1100 0000. 

Мой вопрос: что будет дальше для разных возможных типов x? Если x - подписанный int, то ответ тривиален. Но, если x является подписанным долго, я предполагаю, что ~ 077 станет:

1111 1111 1111 1111 1111 1111 1100 0000 

следующее дополнение 2s для сохранения знака. Это верно?

Кроме того, если х беззнаковое долго будет ~ 077 стать:

0000 0000 0000 0000 1111 1111 1100 0000 

Или, будет ~ 077 быть преобразованы в знаковый длинный первый:

1111 1111 1111 1111 1111 1111 1100 0000 

... после чего преобразуется в unsigned long (без изменения битов)?

Любая помощь поможет мне уточнить, будет ли эта операция всегда установить только последние 6 бит в ноль.

+1

Возможно, вы можете сделать это самостоятельно, используя отладчик для просмотра значений или распечатки значений самостоятельно. Вы также можете посмотреть спецификацию языка C. Выясните, какая спецификация компилятор предположительно реализует, а затем просматривает детали в соответствующей спецификации. «Целое продвижение» - это, вероятно, то, что вы хотите искать. FWIW, я верю в C, что целая реклама не должна меняться. Таким образом, вы, вероятно, получите значение расширенного знака – rliu

ответ

3

Какой бы тип данных вы ни выбрали, ~077 установит самые правые 6 бит на 0 и все остальные на 1.

Если предположить, что 16-разрядные int с и 32-разрядные long с, есть 4 случая:

Case 1

unsigned int x = 077; // x = 0000 0000 0011 1111 
x = ~x; // x = 1111 1111 1100 0000 
unsigned long y = ~x; // y = 0000 0000 0000 0000 1111 1111 1100 0000 

Случай 2

unsigned int x = 077; // x = 0000 0000 0011 1111 
x = ~x; // x = 1111 1111 1100 0000 
long y = ~x; // y = 0000 0000 0000 0000 1111 1111 1100 0000 

Случай 3

int x = 077; // x = 0000 0000 0011 1111 
x = ~x; // x = 1111 1111 1100 0000 
unsigned long y = ~x; // y = 1111 1111 1111 1111 1111 1111 1100 0000 

Случай 4

int x = 077; // x = 0000 0000 0011 1111 
x = ~x; // x = 1111 1111 1100 0000 
long y = ~x; // y = 1111 1111 1111 1111 1111 1111 1100 0000 

См код here. Это означает, что расширение знака выполняется, когда источником является signed. Когда источником является unsigned, бит знака не увеличивается, а левые бит устанавливаются на 0.

+0

Но что произойдет, если ~ 077 - это подписанный int, который затем ANDed с unsigned long? – SpruceMoose

+0

Как насчет: int x = 077; x = ~ x; unsigned long y = x; Что такое y? – SpruceMoose

+0

ОК, я думаю, у меня это есть. Но какова точка расширения знака при преобразовании из подписанного в unsigned, как в случае 3? Знаете ли вы, где я могу найти фактические спецификации C для этого? – SpruceMoose

2
x = x & ~077 //~077=11111111111111111111111111000000(not in every case) 

~077 is a constant evaluated at the complie time so its value will be casted according to the value of x at the compile time так и операция всегда будет уступать последние 6 бит х 0, а остальные биты останется все, что было до и эксплуатации.Как

//let x=256472--> Binary--> 0000 0000 0000 0011 1110 1001 1101 1000 
x = x & ~077; 
// now x = 0000 0000 0000 0011 1110 1001 1100 0000 Decimal--> 256448 

Так последние 6 бит заменяются на 0, независимо от типа данных во время компиляции остальные биты остаются одинаковыми. И в knr написано там The portable form involves no extra cost, since ~077 is a constant expression that can be evaluated at compile time.

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