按字节打印双精度值是反转实际值
Printing byte wise a double value is reversing the actual value
请找到我的示例代码来演示我的问题:
#include<stdio.h>
typedef struct {
char b[8];
} byte_wise_double_t;
typedef union {
byte_wise_double_t bwd;
double val;
} DOUBLE_T;
int main() {
double tmp;
int ii;
DOUBLE_T my_val;
printf("Enter a value:\n");
scanf("%lf", &tmp);
printf("The read number is: %e\n", tmp);
my_val.val = tmp;
printf("Printing the value bytewise:\n");
for (ii=0; ii<8; ii++) {
printf("%02x", (my_val.bwd.b[ii] & 0xff));
}
printf("\nReverse printing the value bytewise:\n");
for (ii=7; ii>=0; ii--) {
printf("%02x", (my_val.bwd.b[ii] & 0xff));
}
return 0;
}
当您输入一个浮点值时,我会按字节打印双精度值,首先按预期的正确顺序,然后按相反的顺序。但事实证明,第二个 print 语句给出了输入 double 的正确十六进制表示。这是一个示例输出:
Enter a value:
11.23456
The read number is: 1.123456e+001
Printing the value bytewise:
47e6913f18782640
Reverse printing the value bytewise:
402678183f91e647
请解释为什么会这样。
我认为这是对小端与大端的误解。
为简单起见,看一个 16 位整数。比方说 0xaa55(十进制 43605)。
默认情况下,这个数字是低字节在低槽,高字节在高槽。
16-bit: 0xaa55
8-bit: byte[1] = 0xaa, byte[0] = 0x55;
你的第一个语句是从右到左打印十六进制,你的第二个语句是从左到右打印十六进制(如你所读)。查看我的小整数示例,您的第一个 for 循环将打印“55”,然后打印 'aa',颠倒低字节和高字节。你的第二个循环打印从高字节到低字节的数字,就像你阅读它一样。
您可能 运行 在 Intel 处理器上使用此代码。该处理器以 little-endian 顺序将值存储在内存中,其中字节从 least significant 字节开始存储。因此,例如,32 位整数 0xdeadbeef
在内存中存储为 "EF BE AD DE"。这也扩展到 64 位整数和双精度数,这解释了您所看到的反转。
如果您想按照您期望的方式打印 double
的十六进制值,请将其与 uint64_t
合并:
typedef union {
uint64_t intval;
double dblval;
} DOUBLE_T;
...
DOUBLE_T my_val;
my_val.dblval = 1.2345;
printf("%016llx\n", my_val.intval);
(注意:这不是可移植的代码:它假定您可以使用 uint64_t
作为 double
的别名,但并非所有系统都适用。但是,它应该适用于 GCC, Clang,或典型英特尔处理器上的 MSVC)。
请找到我的示例代码来演示我的问题:
#include<stdio.h>
typedef struct {
char b[8];
} byte_wise_double_t;
typedef union {
byte_wise_double_t bwd;
double val;
} DOUBLE_T;
int main() {
double tmp;
int ii;
DOUBLE_T my_val;
printf("Enter a value:\n");
scanf("%lf", &tmp);
printf("The read number is: %e\n", tmp);
my_val.val = tmp;
printf("Printing the value bytewise:\n");
for (ii=0; ii<8; ii++) {
printf("%02x", (my_val.bwd.b[ii] & 0xff));
}
printf("\nReverse printing the value bytewise:\n");
for (ii=7; ii>=0; ii--) {
printf("%02x", (my_val.bwd.b[ii] & 0xff));
}
return 0;
}
当您输入一个浮点值时,我会按字节打印双精度值,首先按预期的正确顺序,然后按相反的顺序。但事实证明,第二个 print 语句给出了输入 double 的正确十六进制表示。这是一个示例输出:
Enter a value: 11.23456 The read number is: 1.123456e+001 Printing the value bytewise: 47e6913f18782640 Reverse printing the value bytewise: 402678183f91e647
请解释为什么会这样。
我认为这是对小端与大端的误解。
为简单起见,看一个 16 位整数。比方说 0xaa55(十进制 43605)。
默认情况下,这个数字是低字节在低槽,高字节在高槽。
16-bit: 0xaa55
8-bit: byte[1] = 0xaa, byte[0] = 0x55;
你的第一个语句是从右到左打印十六进制,你的第二个语句是从左到右打印十六进制(如你所读)。查看我的小整数示例,您的第一个 for 循环将打印“55”,然后打印 'aa',颠倒低字节和高字节。你的第二个循环打印从高字节到低字节的数字,就像你阅读它一样。
您可能 运行 在 Intel 处理器上使用此代码。该处理器以 little-endian 顺序将值存储在内存中,其中字节从 least significant 字节开始存储。因此,例如,32 位整数 0xdeadbeef
在内存中存储为 "EF BE AD DE"。这也扩展到 64 位整数和双精度数,这解释了您所看到的反转。
如果您想按照您期望的方式打印 double
的十六进制值,请将其与 uint64_t
合并:
typedef union {
uint64_t intval;
double dblval;
} DOUBLE_T;
...
DOUBLE_T my_val;
my_val.dblval = 1.2345;
printf("%016llx\n", my_val.intval);
(注意:这不是可移植的代码:它假定您可以使用 uint64_t
作为 double
的别名,但并非所有系统都适用。但是,它应该适用于 GCC, Clang,或典型英特尔处理器上的 MSVC)。