2012-10-30 3 views
2

Например:Тильда C без знака против знакового целого числа

unsigned int i = ~0; 

Результата: Максимальное число, которое я могу назначить i

и

signed int y = ~0; 

Результат: -1

Почему я получаю -1? Должен ли я получить максимальное число, которое я могу назначить y?

+2

Вы уверены, что знаете, что оператор ~ делает? (Побитовое NOT) –

+1

Ну, '-1' - это максимальное число, которое вы можете поместить в целое число, но с _maximum_, определяемым как двоичное значение absoltue :) –

ответ

6

И 4294967295 (а.к.а. UINT_MAX) и -1 имеют одинаковое бинарное представление 0xFFFFFFFF или 32 бит весь набор 1. Это связано с тем, что подписанные числа представлены с использованием two's complement. Отрицательное число имеет свой MSB (самый старший бит), установленный в 1, и его значение определяется переворачиванием остальных бит, добавлением 1 и умножением на -1. Поэтому, если у вас установлен MSB 1, а остальные бит также установлены на 1, вы переворачиваете их (получите 32 нули), добавьте 1 (получите 1) и умножьте на -1, чтобы наконец получить -1.

Это упрощает для ЦП выполнение математики, поскольку для отрицательных чисел не требуется особых исключений. Например, попробуйте добавить 0xFFFFFFFF (-1) и 1. Поскольку имеется только место для 32 бит, это будет переполнение, и результат будет 0, как и ожидалось.

Смотри на: ответ

http://en.wikipedia.org/wiki/Two%27s_complement

4

~0 всего лишь int со всеми битами, установленными в 1. При интерпретации unsigned это будет эквивалентно UINT_MAX. При интерпретации signed это будет -1.

Если предположить, что 32 бит Интс:

0 = 0x00000000 = 0 (signed) = 0 (unsigned) 
~0 = 0xffffffff = -1 (signed) = UINT_MAX (unsigned) 
+0

Спасибо, но почему 0xffffffff равно -1 в подписанном? – user1365914

+0

~ 0 = 0xffffffff = -1 (подпись, -1 в форме дополнения 2). Вся система придерживается такого подхода? – SparKot

+0

присваивание не является повторной интерпретацией, но преобразование значения: '~ 0' при присвоении' unsigned int' приведет только к 'UINT_MAX', если' ~ 0' типа 'int' представляет' -1' – Christoph

1

Нет, потому что ~ является побитового НЕ оператора, а не максимального значения для типа оператора. ~0 соответствует int со всеми битами, установленными на 1, который, интерпретируемый как unsigned, дает вам максимальное число, представляемое без знака, и интерпретируется как подписанный int, дает вам -1.

0

Вы должны быть на машине two's complement.

+0

Краткая дискуссия об альтернативной системе и том, как она не используется сегодня : http://en.wikipedia.org/wiki/Ones%27_complement#History – hyde

+0

Язык C допускает дополнение двух дополнений, дополнений и знаков, основанных на базовом оборудовании, поэтому он не полностью не используется. Если бы какой-то аппаратный фактор (скорость или стоимость) использовал одно из других представлений, я бы сказал, что они вернутся. – ldav1s

2

Павла совершенно прав.Вместо того, чтобы использовать ~ 0, вы можете использовать:

#include <limits.h> 

signed int y = INT_MAX; 
unsigned int x = UINT_MAX; 

А теперь, если вы проверяете значение:

printf("x = %u\ny = %d\n", UINT_MAX, INT_MAX); 

вы можете увидеть максимальные значения в вашей системе.

5
unsigned int i = ~0; 

Результат: Максимальное число, которое я могу назначить я

Обычно, но не обязательно. Выражение ~0 оценивает значение int со всеми (не заполняющими) битами. Стандарт C позволяет использовать три представления для целых чисел,

  • дополнения до двух, в этом случае ~0 = -1 и назначая, что к unsigned int результатам в (-1) + (UINT_MAX + 1) = UINT_MAX.
  • их дополнение, и в этом случае ~0 представляет собой либо отрицательное ноль, либо ловушку; если это отрицательный нуль, то присваивание unsigned int результатов в 0.
  • знак-и величины, в этом случае ~0 является INT_MIN == -INT_MAX, и назначение его к unsigned int результатов в (UINT_MAX + 1) - INT_MAX, что 1 в маловероятном случае, что unsigned int имеет ширину (количество битов значения для целых чисел без знака, число битов значения + 1 [для знакового бита] для целых типов со знаком) меньше, чем значение int и 2^(WIDTH - 1) + 1, в общем случае, что ширина unsigned int такая же, как ширина int.

Инициализация

unsigned int i = ~0u; 

всегда будет приводить к i держа значение UINT_MAX.

signed int y = ~0; 

Результат: -1

Как было указано выше, только если представление целых чисел использует двоичное дополнение (который в настоящее время является на сегодняшний день наиболее распространенным представлением).

0

Посмотрите http://en.wikipedia.org/wiki/Two%27s_complement и узнайте немного о булевой алгебре и логическом дизайне. Изучение того, как считать в двоичном и сложение и вычитание в двоичном коде, объяснит это далее.

Язык C использовал эту форму чисел, чтобы найти наибольшее количество, которое вам нужно использовать 0x7FFFFFFF. (где вы используете 2 FF для каждого байта, а самый левый байт - 7.) Чтобы понять это, вам нужно искать шестнадцатеричные числа и то, как они работают.

Теперь, чтобы объяснить неподписанный эквивалент. В подписанных числах нижняя половина чисел отрицательна (0 считается положительной, поэтому отрицательные числа на самом деле считают 1 выше положительных чисел). Беззнаковые числа положительны. Поэтому теоретически ваше наивысшее число для 32-битного int равно 2^32, за исключением того, что 0 все еще считается положительным, так что это фактически 2^32-1, теперь для подписанных чисел половина этих чисел отрицательна.что означает, что мы делим предыдущее число 2^32 на 2, так как 32 является показателем, мы получаем 2^31 чисел на каждой стороне 0, положительный означает, что диапазон подписанного 32-битного int равен (-2^31, 2^31- 1).

Теперь просто сравнивающие диапазоны: 32 бит без знака INT: (0, 2^32-1) подписал 32 бит INT: (-2^31, 2^32-1) беззнаковое 16 бит INT: (0 , 2^16-1) подписан 16 бит int: (-2^15, 2^15-1)

вы должны быть в состоянии увидеть рисунок здесь. , чтобы объяснить, что вещь ~ 0 занимает немного больше, это связано с вычитанием в двоичном формате. это просто добавление 1 и переворачивание всех бит, а затем добавление двух чисел вместе. C делает это за кулисами, и поэтому многие процессоры (включая строки процессоров x86 и x64). Из-за этого лучше всего хранить отрицательные числа, как если бы они отсчитывали, а в двух дополнениях добавленный 1 также скрытый. Потому что 0 считается положительным, поэтому отрицательные числа не могут иметь значение для 0, поэтому они автоматически добавляют к ним -1 (положительный 1 после бит-флип). при декодировании отрицательных чисел мы должны учитывать это.

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