Более описательная версия происходящего:
Вы объявляете переменную a
, которая будет содержать 32-битное значение.Компилятор знает, что нужно обрабатывать a
как целое число со знаком, но во время выполнения единственное, что знает компьютер, это то, что он хранит 32 бита.
(a) -> 00000000
Далее вы устанавливаете неподписанное целое i
вуказать на это значение.
(*i) --+---> 00000000
(a) --+
Таким образом, a и i ссылаются на одно и то же 32-битное значение, однако, в зависимости от их типов, это значение может интерпретироваться по-разному ...
Затем вы устанавливаете *i
быть ~0
(*i) --+---> FFFFFFFF
(a) --+
И тогда вы печатаете %d
из a
.Итак, во-первых, a
подписано, но это не главное.Важно то, что вы передаете 0xFFFFFFFF
в качестве параметра printf("%d"...)
.При выполнении printf библиотека libc видит %d
- это указывает компилятору ожидать значение, представляющее 32-разрядное целое число со знаком (*), и поэтому для его преобразования компилятор будет использовать преобразователь целого числа в ascii со знаком.к читабельному человеку тексту.Поскольку старший бит равен единице, этот интерпретатор показывает это как отрицательное число.
Я предполагаю, что вы используете систему, которая использует 32-битное целое число.В некоторых системах используется 16-битное int, но тот же принцип применяется, если вы используете 16-битный
(*) - в зависимости от того, для какой системы компилируется, %d
может представлять либо 32или 16-битное целое число ... Вы не должны предполагать, что %d
относится только к 32-битному ...