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