#include <stdio.h>
typedef unsigned char*pointer;
void show_bytes(pointer start, size_t len)
{
size_t i;
for (i = 0; i < len; i++)
printf("%p\t0x%04x\n",start+i, start[i]);
printf("\n");
}
int main()
{
double a = 4.75;
printf("Double demo by %s on %s %s\n", "Toan Tran", __DATE__, __TIME__);
printf("Double a = %.2f (0x%08x)\n", a, a);
show_bytes((pointer) &a, sizeof(double));
}
输出:
Double demo by Toan Tran on Nov 8 2018 11:07:07
Double a = 4.75 (0x00000100)
0x7ffeee7a0b38 0x0000
0x7ffeee7a0b39 0x0000
0x7ffeee7a0b3a 0x0000
0x7ffeee7a0b3b 0x0000
0x7ffeee7a0b3c 0x0000
0x7ffeee7a0b3d 0x0000
0x7ffeee7a0b3e 0x0013
0x7ffeee7a0b3f 0x0040
对于此行:
printf("Double a = %.2f (0x%08x)\n", a, a);
我希望它打印出start[i]
的结果
返回的十六进制不是double的正确值。
我希望它返回0x40130000000000 ...
请帮助。
答案 0 :(得分:3)
%x
格式说明符期望使用unsigned int
参数,但是您传入的是double
。使用错误的格式说明符会调用undefined behavior。
要打印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);
答案 1 :(得分:0)
要允许打印 any 对象的十六进制转储,请传递其地址和长度。
void show_bytes2(void *start, size_t size) {
int nibble_width_per_byte = (CHAR_BIT + 3) / 4; // Often 2
unsigned char *mem = start;
// Highest bytes first
for (size_t i = size; i>0; ) {
printf("%0*x", nibble_width_per_byte, mem[--i]);
}
printf("\n");
// Lowest bytes first
while (size--) {
printf("%0*x", nibble_width_per_byte, *mem++);
}
printf("\n");
}
使用"%a"
以十六进制形式显示double
的有效数字。
int main() {
double a = 4.75;
printf("Double a = %a %e %f %g\n", a, a, a, a);
show_bytes2(&a, sizeof a);
}
输出
Double a = 0x1.3p+2 4.750000e+00 4.750000 4.75
4013000000000000 // I want it to return 0x40130000000000...
0000000000001340