Ответ 1
#include <inttypes.h>
#include <stdint.h>
printf("%016" PRIxPTR "\n", (uintptr_t)ptr);
но он не будет печатать указатель в определенном порядке реализации (говорит DEAD:BEEF
для сегментированного режима 8086).
В C, я бы хотел использовать printf для отображения указателей, и поэтому они правильно выстраиваются в линию, я хотел бы добавить их в 0s.
Я предполагал, что правильный способ сделать это:
printf("%016p", ptr);
Это работает, но этот gcc жалуется на следующее сообщение:
warning: '0' flag used with ‘%p’ gnu_printf format
Я немного искал его, и следующий поток относится к одной теме, но на самом деле не дает решения.
http://gcc.gnu.org/ml/gcc-bugs/2003-05/msg00484.html
Считая, что причина, по которой gcc жалуется, заключается в том, что предложенный мной синтаксис не определен в C99. Но я не могу найти другого способа сделать то же самое стандартным одобренным способом.
Итак, вот двойной вопрос:
#include <inttypes.h>
#include <stdint.h>
printf("%016" PRIxPTR "\n", (uintptr_t)ptr);
но он не будет печатать указатель в определенном порядке реализации (говорит DEAD:BEEF
для сегментированного режима 8086).
Использование:
#include <inttypes.h>
printf("0x%016" PRIXPTR "\n", (uintptr_t) pointer);
Или используйте другой вариант макросов из этого заголовка.
Также обратите внимание, что некоторые реализации printf()
печатают '0x
' перед указателем; другие не делают (и оба правильны в соответствии со стандартом C).
Единственный переносимый способ печати значений указателя - использовать спецификатор "%p"
, который создает выход, определенный реализацией. (Преобразование в uintptr_t
и использование PRIxPTR
, скорее всего, сработает, но (a) uintptr_t
был введен в C99, поэтому некоторые компиляторы могут его не поддерживать, и (b) он не гарантированно существует даже на C99 (там может не быть целым типом, достаточно большим для хранения всех возможных значений указателя.
Поэтому используйте "%p"
с sprintf()
(или snprintf()
, если он у вас есть), чтобы напечатать строку, а затем распечатать заполнение строки ведущими пробелами.
Одна из проблем заключается в том, что нет действительно хорошего способа определить максимальную длину строки, созданной "%p"
.
Это, по общему признанию, неудобно (хотя, конечно, вы можете обернуть его в функцию). Если вам не нужна 100% -ная переносимость, я никогда не использовал систему, набрав указатель на unsigned long
, и печать результата с помощью "0x%16lx"
не сработала. (Или вы можете использовать "0x%*lx"
и вычислить ширину, возможно, что-то вроде sizeof (void*) * 2
. Если вы действительно параноик, вы можете учитывать системы, где CHAR_BIT > 8
, поэтому вы получите более двух шестнадцатеричных цифр на каждый байт. )
Этот ответ аналогичен приведенному ранее в fooobar.com/questions/145228/..., но также учитывает возможные ширины (как указано fooobar.com/questions/145228/..., который я не узнал, пока мой ответ не был показан ниже;). Следующие отрезанные будут печатать указатели в виде 8 0-шестнадцатеричных символов на машинах с обычным *, где они могут быть представлены 32 битами, 16 на 64b и 4 на 16b-системах.
#include <inttypes.h>
#define PRIxPTR_WIDTH ((int)(sizeof(uintptr_t)*2))
printf("0x%0*" PRIxPTR, PRIxPTR_WIDTH, (uintptr_t)pointer);
Обратите внимание на использование символа звездочки для выбора ширины следующим аргументом, который находится на C99 (вероятно, до?), но который редко встречается "в дикой природе". Это лучше, чем использование преобразования p
, потому что последнее определяется реализацией.
* Стандарт позволяет uintptr_t
быть больше, чем минимум, но я предполагаю, что нет реализации, которая не использует минимум.
Это легко решить, если вы указали указатель на длинный тип. Проблема в том, что это не будет работать на всех платформах, поскольку предполагается, что указатель может вписываться в длинный и что указатель может отображаться в 16 символах (64 бита). Однако это справедливо на большинстве платформ.
чтобы оно стало следующим:
printf("%016lx", (unsigned long) ptr);
Как уже говорилось в вашей ссылке, поведение undefined. Я не думаю, что это переносимый способ сделать это, так как% p зависит от платформы, над которой вы работаете. Конечно, вы можете просто направить указатель на int и отобразить его в шестнадцатеричном формате:
printf("0x%016lx", (unsigned long)ptr);
Возможно, это будет интересно (с 32-битной Windows-машины, используя mingw):
[email protected] /u
$ cat test.c
#include <stdio.h>
int main()
{
char c;
printf("p: %016p\n", &c);
printf("x: %016llx\n", (unsigned long long) (unsigned long) &c);
return 0;
}
[email protected] /u
$ gcc -Wall -o test test.c
test.c: In function `main':
test.c:7: warning: `0' flag used with `%p' printf format
[email protected] /u
$ ./test.exe
p: 0022FF77
x: 000000000022ff77
Как вы можете видеть, версия% p поддерживает нули в размере указателя, а затем пробелы до указанного размера, тогда как использование% x и casts (спецификаторы отливок и форматирования очень не переносимы) использует только нули.
Обратите внимание, что если указатель печатает с префиксом "0x", вам нужно будет заменить "% 018p" для компенсации.
Обычно я использую% x для отображения указателей. Я полагаю, что он не переносится в 64-битные системы, но он отлично работает для 32-биттеров.
Мне будет интересно узнать, какие ответы есть для переносных решений, поскольку представление указателя не совсем переносимо.