Разница между печатью адреса памяти с использованием% u и% d в C?

Я читаю книгу C. Чтобы распечатать адрес памяти переменной, иногда в книге используется:

printf("%u\n",&n);

Иногда автор писал:

printf("%d\n",&n);

Результат всегда один и тот же, но я не понимаю различий между ними (я знаю% u для unsigned).

Может ли кто-нибудь уточнить это, пожалуйста?

Большое спасибо.

Ответ 1

%u обрабатывает целое число как unsigned, тогда как %d обрабатывает целое число как подписанное. Если целое число находится между 0 an 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 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.

Ответ 2

%d и %u будут печатать те же результаты, когда старший бит не установлен. Тем не менее, это не переносимый код, и это не хороший стиль. Надеюсь, ваша книга лучше, чем кажется из этого примера.

Ответ 3

Какое значение вы пробовали? Разница без знака и подписанная, как вы сказали, знаете. Итак, что он сделал и что вы ожидали?

Положительные подписанные значения выглядят так же, как и без знака, поэтому могу ли я предположить, что вы использовали меньшее значение для тестирования? Что относительно отрицательного значения?

Наконец, если вы пытаетесь распечатать адрес переменной (как вам кажется), вместо этого используйте% p.

Ответ 4

Все адреса являются неподписанными 32-разрядными или 64-разрядными в зависимости от машины (не могут записываться на отрицательный адрес). Использование% d не подходит, но обычно работает. Рекомендуется использовать% u или% ul.