2013-09-30 3 views
1

В чем разница между (unsigned)~0 и (unsigned)1. Почему unsigned от ~0 является -1 и unsigned из 1 является 1? Имеет ли это какое-то отношение к тому, как в памяти хранятся неподписанные числа. Почему число без знака дает подписанный результат. Это также не приводило к ошибкам переполнения. Я использую GCC компилятора:Разница между '(без знака) 1' и '(без знака) ~ 0'

#include<sdio.h> 
main() 
{ 
unsigned int x=(unsigned)~0; 
unsigned int y=(unsigned)1; 
printf("%d\n",x); //prints -1 
printf("%d\n",y); //prints 1 
} 
+0

Не поведение '~ 0' является зависимым от реализации: [Расчет диапазонов типов данных в C] (http://stackoverflow.com/questions/17796041/calculating-ranges-of-data-types-in-c/17796122 # 17796122) –

ответ

5

Поскольку %d является знаковой INT спецификатора. Используйте %u.

который печатает 4294967295 на моей машине.

Как уже упоминалось, если вы интерпретируете самое высокое значение без знака как подписанное, вы получаете -1, см. Запись в wikipedia для two's complement.

+0

Ох спасибо!и почему это не только 1 вместо 4294967295 – programer8

+0

, потому что оператор инвертирует * все * биты. –

+0

'~' является побитовым оператором и переворачивает все биты. Может быть, вы думаете о '!' (Логическом нет), который, вероятно, даст вам 1 вместо этого. – Dmitri

1

Ваша система использует two's complement представление отрицательных чисел. В этом представлении двоичное число, составленное из всех, представляет наибольшее отрицательное число -1.

Поскольку инвертирования всех битов из нуля дает ряд, состоящий из всех из них, вы получаете -1 когда вы повторно интерпретировать число как число со знаком, распечатав его с %d который ожидает подписал номер, а не без знака.

+0

спасибо, что объясняет. – programer8

0

printf() только знает, какую переменную вы передали с помощью каких спецификаторов формата, которые вы использовали в строке форматирования. Итак, что происходит здесь, так это то, что вы печатаете x и y, так как подписали целые числа, потому что вы использовали %d в своей строке формата. Вместо этого попробуйте %u, и вы получите результат в соответствии с тем, что вы, вероятно, ожидаете.

1

Во-первых, при использовании printf вы сообщаете ему, чтобы напечатать номер как подписанный («% d») вместо unsigned («% u»).

Во-вторых, вы правы в том, что оно «имеет какое-то отношение к тому, как номера хранятся в памяти». Int (подписанный или неподписанный) не является одним битом на вашем компьютере, а представляет собой набор из k бит. Точное значение k зависит от особенностей вашей компьютерной архитектуры, но, скорее всего, у вас есть k = 32.

Для краткости давайте предположим, что ваши ints имеют длину 8 бит, поэтому k = 8 (это, безусловно, не так, если только вы не работаете с очень ограниченной встроенной системой). В этом случае (int) 0 фактически является 00000000, а (int) ~ 0 (что отрицает все биты) равно 11111111.

Наконец, в дополнении 2 (которое является наиболее распространенным двоичным представлением числа со знаком), 11111111 на самом деле -1. См. http://en.wikipedia.org/wiki/Two 's_complement для описания дополнения двух.

Если вы изменили печать на «% u», тогда она напечатает положительное целое число, которое представляет (2^k-1), где k - количество бит в целых числах (возможно, оно напечатает 4294967295) ,

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