Преобразование типа: signed int в unsigned long в C

В настоящее время я дохожу до главы 2 языка программирования C (K&R) и читаю о побитовых операциях.

Вот пример, который вызвал мое любопытство:

x = x & ~077

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

0000 0000 0011 1111 (16 bit signed int).

Затем это будет дополнено:

1111 1111 1100 0000.

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

1111 1111 1111 1111 1111 1111 1100 0000

следующие 2s дополнение, чтобы сохранить знак. Это правильно?

Кроме того, если x является unsigned long, ~077 станет:

0000 0000 0000 0000 1111 1111 1100 0000

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

1111 1111 1111 1111 1111 1111 1100 0000

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

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


person SpruceMoose    schedule 03.12.2013    source источник
comment
Вероятно, вы можете выполнить этот тест самостоятельно, либо используя отладчик для просмотра значений, либо самостоятельно распечатав значения. Вы также можете посмотреть спецификацию языка C. Выясните, какую спецификацию предположительно реализует ваш компилятор, а затем найдите подробности в соответствующей спецификации. Целочисленное продвижение, вероятно, то, что вы хотите искать. FWIW, я считаю, что в C целочисленное продвижение не должно изменять значение. Таким образом, вы, вероятно, получите расширенное значение знака   -  person rliu    schedule 03.12.2013


Ответы (2)


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

Предполагая 16-битные ints и 32-битные longs, есть 4 случая:

Дело 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

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

person Sufian Latif    schedule 03.12.2013
comment
Но что произойдет, если ~077 является целым числом со знаком, которое затем объединяется по И с беззнаковым длинным? - person SpruceMoose; 03.12.2013
comment
А как насчет: int x = 077; х = ~ х; беззнаковый длинный у = х; Что ты? - person SpruceMoose; 03.12.2013
comment
Хорошо, я думаю, что понял. Но в чем смысл расширения знака при преобразовании из знакового в беззнаковый, как в случае 3? Вы знаете, где я могу найти фактические спецификации C для этого? - person SpruceMoose; 03.12.2013
comment
Погуглил это, надеюсь, помогает :) И Когда целое число с отрицательным знаком преобразуется в беззнаковое целое того же или большего типа, оно сначала преобразуется в знаковый эквивалент большего типа, а затем преобразуется в беззнаковое значение. из здесь. - person Sufian Latif; 03.12.2013

 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 битам x до 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 независимо от типа данных во время компиляции, остальные биты остаются неизменными. А в кнр там написано The portable form involves no extra cost, since ~077 is a constant expression that can be evaluated at compile time.

person APan    schedule 03.12.2013