Спецификатор формата %x
ожидает аргумент unsigned int
, но вы передаете double
. Использование неправильного спецификатора формата вызывает неопределенное поведение .
Чтобы напечатать представление double
, вам необходимо напечатать каждый отдельный байт в шестнадцатеричном виде с использованием символьного указателя. Это именно то, что вы делаете в show_bytes
, и это правильный способ сделать это.
Кроме того, при печати указателя со спецификатором формата %p
вы должны привести указатель к void *
, чего и ожидает %p
. Это один из редких случаев, когда требуется приведение к void *
.
У вас может возникнуть соблазн сделать что-то вроде этого:
printf("%llx", *((unsigned long long *)&a));
Однако это нарушение строгого правила наложения имен. Вам нужно будет использовать memcpy
для копирования байтов в другой тип:
static_assert(sizeof(unsigned long long) == sizeof(double));
unsigned long long b;
memcpy(&b, &a, sizeof(a));
printf("%llx", b);
Вы также можете сделать это с помощью объединения:
union dval {
double d;
unsigned long long u;
};
union dval v;
v.d = d;
printf("%llx", v.u);