Спецификатор формата %u
фактически принимает строковое представление целого числа со знаком, а результат преобразуется в целое число без знака.
Раздел 7.21.6.2p12 стандарта C относительно функции fscanf
(и, соответственно, scanf
) говорит следующее о спецификаторе преобразования u
:
Соответствует необязательному десятичному целому числу со знаком, формат которого совпадает с ожидаемым для предметной последовательности функции strtoul
со значением 10 для аргумента base
. Соответствующим аргументом должен быть указатель на целое число без знака.
Преобразование из знака в без знака происходит путем логического добавления максимального значения, которое тип без знака может содержать +1, к значению цифры 10 * * со знаком введите, пока результат не окажется в диапазоне без знака. Обратите внимание, что это происходит независимо от базового представления соответствующих целочисленных типов.
Так, например, предполагая, что size_t
является 64-битным типом, наибольшее значение, которое он может содержать, равно 18446744073709551615. Поэтому, если вы введете -1 затем 18446744073709551616 добавляется к -1, чтобы получить 18446744073709551615, который является результатом.
Это преобразование задокументировано в разделе 6.3.1.3:
1 Когда значение с целочисленным типом преобразуется в другой целочисленный тип, отличный от _Bool
, если значение может быть представлено новым типом, оно не изменяется.
2 В противном случае, если новый тип без знака, значение преобразуется путем многократного сложения или вычитания более одного максимального значения, которое может быть представлено в новом типе, до тех пор, пока значение не окажется в диапазоне нового типа.
3 В противном случае новый тип подписывается и значение не может быть представлено в нем; либо результат определяется реализацией, либо определяется сигнал реализации.