使用 memcpy 转换字节数据
Converting byte data using memcpy
我正在尝试编写一个 C 程序来读取检测数据块并将特定字节提取到变量中。数据是混合格式,例如字节 4-5 是 integer
、bytes
10-14 是浮点数等。
我编写了一个实验程序来测试从字节 (char) 数组中提取值,但我不明白结果。我的测试程序是 运行 在 Raspberry Pi 3 运行 Debian Jessie 上。
这是我的程序:
将字节数组转换为部分
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
// Test Data Array
unsigned char v1[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x40, 0xB1, 0x10, 0x55, 0xEE, 0x5A, 0xC7, 0x39,
0xBB, 0x22, 0x04, 0xB2, 0xF4, 0xF5, 0xF6, 0xF7,
0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFF, 0x87};
signed char c; // 1-byte
unsigned char u; // 1-byte
signed short i; // 2-byte
unsigned short j; // 2-byte
signed int k; // 4-byte
unsigned int l; // 4-byte
signed long long m; // 8-byte
unsigned long long n; // 8-byte
float x; // 4-byte
double y; // 8-byte
long double z; // 8-byte
// Display type sizes
printf("\nsizeof's: %u %u %u %u %u %u %u %u \n\n",sizeof(char),
sizeof(short),sizeof(int),sizeof(long),sizeof(long long),
sizeof(float),sizeof(double),sizeof(long double));
printf("Addresses: \n");
printf(" %08X\n %08X\n %08X\n %08X\n %08X\n %08X\n %08X\n %08X\n %08X\n %08X\n %08X\n\n",
&c,&u,&i,&j,&k,&l,&m,&n,&x,&y,&z);
// Display Endianess
unsigned int e1 = 1;
char *e2 = (char *)&e1;
if (*e2)
printf("Little Endian\n\n");
else
printf("Big Endian\n\n");
// Copy bytes to assorted variables
memcpy(&i,&v1[30],2);
printf("Signed Short: %04X %hd\n",i,i); // FF 87
memcpy(&j,&v1[30],2);
printf("Unsigned Short: %04X %hu\n",j,j); // FF 87
memcpy(&k,&v1[16],4);
printf("Signed Int: %08X %d\n",k,k); // BB 22 04 B2
memcpy(&l,&v1[16],4);
printf("Unsigned Int: %08X %u\n",l,l); // BB 22 04 B2
memcpy(&x,&v1[8],4);
printf("Float: %08X %f\n",x,x); // 40 B1 10 55
memcpy(&y,&v1[8],8);
printf("Double: %16X %lf\n",y,y); // 40 B1 10 55 EE 5A C7 39
}
我得到的结果:
pi@raspberrypi:~/Desktop $ ./convertIt_bytes2
sizeof's: 1 2 4 4 8 4 8 8
Addresses:
7EA7E5DB
7EA7E5DA
7EA7E5D8
7EA7E5D6
7EA7E5D0
7EA7E5CC
7EA7E5C0
7EA7E5B8
7EA7E5B4
7EA7E5A8
7EA7E5A0
Little Endian
Signed Short: FFFF87FF -30721
Unsigned Short: 87FF 34815
Signed Int: B20422BB -1308351813
Unsigned Int: B20422BB 2986615483
Float: 7EA7E5E8 9943184834560.000000
Double: 7EA7E5EC 0.000000
memcpy
使用的字体大小从我打印的 sizeof's
看起来是正确的,那么为什么我的输出只有部分正确? Signed Short
十六进制值打印为 8 个字符而不是 4 个字符,即使它是一个用 %04X
打印的 2 字节字。
随后的 unsigned short 和 int 输出是正确的,但以下 float 和 double hex 值是垃圾并且似乎 addresses
不是值,因为输出接近上面打印的变量地址。这是怎么回事?
取以下内容:
memcpy(&i,&v1[30],2);
printf("Signed Short: %04X %hd\n",i,i); // FF 87
将字符和短裤作为参数传递给可变参数函数,例如 printf
将导致这些参数隐式转换为整数。
i
是 "short"(16 位)。当它被传递给 printf
时,if 在进入堆栈之前被转换为 int(32 位)。这包括符号扩展。 0xff87 是一个负数(简称)。因此 0xff87 在打印之前被强制转换为 0xffffff87。
作为学习练习,试试这个:
printf("Signed Short: %04X %hd\n",(unsigned short)i,(unsigned short) i); // FF 87
这将强制从 short 到 unsigned short 到 integer 的强制转换。这与从短整数到整数不同。
更新:既然你问了"printing a double value in hex form"。您基本上需要将保存该值的地址解释为十六进制字节数组。例如:
double d = 3.14159;
unsigned char* ptr = (unsigned char*)&d;
for (size_t i = 0; i < sizeof(double); i++)
printf("%02x ", ptr[i]);
打印:
6e 86 1b f0 f9 21 09 40
字节顺序可能与您预期的不同,因为我 运行 在 x86 Intel 上。 Little Endian(或英特尔自己的特定布局)可能会影响浮点的内存字节顺序。
我正在尝试编写一个 C 程序来读取检测数据块并将特定字节提取到变量中。数据是混合格式,例如字节 4-5 是 integer
、bytes
10-14 是浮点数等。
我编写了一个实验程序来测试从字节 (char) 数组中提取值,但我不明白结果。我的测试程序是 运行 在 Raspberry Pi 3 运行 Debian Jessie 上。
这是我的程序:
将字节数组转换为部分
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
// Test Data Array
unsigned char v1[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x40, 0xB1, 0x10, 0x55, 0xEE, 0x5A, 0xC7, 0x39,
0xBB, 0x22, 0x04, 0xB2, 0xF4, 0xF5, 0xF6, 0xF7,
0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFF, 0x87};
signed char c; // 1-byte
unsigned char u; // 1-byte
signed short i; // 2-byte
unsigned short j; // 2-byte
signed int k; // 4-byte
unsigned int l; // 4-byte
signed long long m; // 8-byte
unsigned long long n; // 8-byte
float x; // 4-byte
double y; // 8-byte
long double z; // 8-byte
// Display type sizes
printf("\nsizeof's: %u %u %u %u %u %u %u %u \n\n",sizeof(char),
sizeof(short),sizeof(int),sizeof(long),sizeof(long long),
sizeof(float),sizeof(double),sizeof(long double));
printf("Addresses: \n");
printf(" %08X\n %08X\n %08X\n %08X\n %08X\n %08X\n %08X\n %08X\n %08X\n %08X\n %08X\n\n",
&c,&u,&i,&j,&k,&l,&m,&n,&x,&y,&z);
// Display Endianess
unsigned int e1 = 1;
char *e2 = (char *)&e1;
if (*e2)
printf("Little Endian\n\n");
else
printf("Big Endian\n\n");
// Copy bytes to assorted variables
memcpy(&i,&v1[30],2);
printf("Signed Short: %04X %hd\n",i,i); // FF 87
memcpy(&j,&v1[30],2);
printf("Unsigned Short: %04X %hu\n",j,j); // FF 87
memcpy(&k,&v1[16],4);
printf("Signed Int: %08X %d\n",k,k); // BB 22 04 B2
memcpy(&l,&v1[16],4);
printf("Unsigned Int: %08X %u\n",l,l); // BB 22 04 B2
memcpy(&x,&v1[8],4);
printf("Float: %08X %f\n",x,x); // 40 B1 10 55
memcpy(&y,&v1[8],8);
printf("Double: %16X %lf\n",y,y); // 40 B1 10 55 EE 5A C7 39
}
我得到的结果:
pi@raspberrypi:~/Desktop $ ./convertIt_bytes2
sizeof's: 1 2 4 4 8 4 8 8
Addresses: 7EA7E5DB 7EA7E5DA 7EA7E5D8 7EA7E5D6 7EA7E5D0 7EA7E5CC 7EA7E5C0 7EA7E5B8 7EA7E5B4 7EA7E5A8 7EA7E5A0
Little Endian
Signed Short: FFFF87FF -30721
Unsigned Short: 87FF 34815
Signed Int: B20422BB -1308351813
Unsigned Int: B20422BB 2986615483
Float: 7EA7E5E8 9943184834560.000000
Double: 7EA7E5EC 0.000000
memcpy
使用的字体大小从我打印的 sizeof's
看起来是正确的,那么为什么我的输出只有部分正确? Signed Short
十六进制值打印为 8 个字符而不是 4 个字符,即使它是一个用 %04X
打印的 2 字节字。
随后的 unsigned short 和 int 输出是正确的,但以下 float 和 double hex 值是垃圾并且似乎 addresses
不是值,因为输出接近上面打印的变量地址。这是怎么回事?
取以下内容:
memcpy(&i,&v1[30],2);
printf("Signed Short: %04X %hd\n",i,i); // FF 87
将字符和短裤作为参数传递给可变参数函数,例如 printf
将导致这些参数隐式转换为整数。
i
是 "short"(16 位)。当它被传递给 printf
时,if 在进入堆栈之前被转换为 int(32 位)。这包括符号扩展。 0xff87 是一个负数(简称)。因此 0xff87 在打印之前被强制转换为 0xffffff87。
作为学习练习,试试这个:
printf("Signed Short: %04X %hd\n",(unsigned short)i,(unsigned short) i); // FF 87
这将强制从 short 到 unsigned short 到 integer 的强制转换。这与从短整数到整数不同。
更新:既然你问了"printing a double value in hex form"。您基本上需要将保存该值的地址解释为十六进制字节数组。例如:
double d = 3.14159;
unsigned char* ptr = (unsigned char*)&d;
for (size_t i = 0; i < sizeof(double); i++)
printf("%02x ", ptr[i]);
打印:
6e 86 1b f0 f9 21 09 40
字节顺序可能与您预期的不同,因为我 运行 在 x86 Intel 上。 Little Endian(或英特尔自己的特定布局)可能会影响浮点的内存字节顺序。