%u
рассматривает целое число как беззнаковое, тогда как %d
рассматривает целое число как подписанное.Если целое число находится в диапазоне от 0 до INT_MAX
(что составляет 2 31 -1 в 32-разрядных системах), то выходные данные идентичны для обоих случаев.
Это имеет значение толькоесли целое число отрицательное (для входных данных со знаком) или между INT_MAX+1
и UINT_MAX
(например, между 2 31 и 2 32 -1).В этом случае, если вы используете спецификатор %d
, вы получите отрицательное число, тогда как, если вы используете %u
, вы получите большое положительное число.
Адреса имеют смысл только как беззнаковыечисла, так что нет никакой причины печатать их как числа со знаком.Кроме того, когда они распечатываются, они обычно печатаются в шестнадцатеричном (с указателем формата %x
), а не в десятичном формате.
Вам действительно нужно просто использовать спецификатор формата %p
для адресов, хотяон гарантированно работает для всех действительных указателей.Если вы работаете в системе с 32-разрядными целыми числами, но с 64-разрядными указателями, если вы пытаетесь напечатать указатель с любым из %d
, %u
или %x
без модификатора длины ll
, вы 'получит неправильный результат для этого и всего остального, что будет напечатано позже (потому что printf
читает только 4 из 8 байтов аргумента указателя);если вы добавите модификатор длины ll
, то вы не сможете переносить его на 32-разрядные системы.
Итог: всегда используйте %p
для распечатки указателей / адресов:
printf("The address of n is: %p\n", &n);
// Output (32-bit system): "The address of n is: 0xbffff9ec"
// Output (64-bit system): "The address of n is: 0x7fff5fbff96c"
Точный формат вывода определяется реализацией (C99 §7.19.6.1 / 8), но он почти всегда печатается в виде шестнадцатеричного числа без знака, обычно с начальным 0x
.