Предположим, что int
и unsigned int
являются 32-битными, что имеет место на большинстве платформ, которые вы, вероятно, будете использовать (как 32-битные, так и 64-битные системы). Тогда константа 0xFFFFFFFF
имеет тип unsigned int
и имеет значение 4294967295.
Это:
int n = 0xFFFFFFFF;
неявно преобразует это значение из unsigned int
в int
. Результат преобразования определяется реализацией; нет неопределенного поведения. (В принципе, это также может вызывать сигнал, определяемый реализацией, но я не знаю ни одной реализации, которая бы это делала).
Скорее всего, значение, хранящееся в n
, будет -1
.
printf("%u\n", n);
Здесь вы используете спецификатор формата %u
, для которого требуется аргумент типа unsigned int
, но вы передаете ему аргумент типа int
. Стандарт гласит, что значения соответствующего типа со знаком и без знака являются взаимозаменяемыми в качестве аргументов функции, но только для значений, которые находятся в диапазоне обоих типов, что здесь не так.
Этот вызов не выполняет преобразование из int
в unsigned int
. Скорее, значение int
передается в printf
, что предполагает , что полученное значение имеет тип unsigned int
. Поведение не определено. (Опять же, это было бы разумно предупредить.)
Наиболее вероятный результат состоит в том, что значение int
-1
, которое (при условии дополнения 2-х) имеет то же представление, что и 0xFFFFFFFF
, будет обрабатываться так, как если бы оно было unsigned int
значением 0xFFFFFFFF
, который печатается в десятичном виде как 4294967295
.
Вы можете получить предупреждение о int n = 0xFFFFFFFF;
, используя опцию -Wconversion
или -Wsign-conversion
. Эти опции не включены в -Wextra
или -Wall
. (Вы должны спросить сопровождающих gcc, почему.)
Я не знаю опции, которая вызовет предупреждение при вызове printf
.
(Конечно, исправление состоит в том, чтобы определить n
как unsigned int
, что делает все правильно и согласованно.)