gpt4 book ai didi

使用 memcpy 转换字节数据

转载 作者:太空宇宙 更新时间:2023-11-04 03:18:54 28 4
gpt4 key购买 nike

我正在尝试编写一个 C 程序来读取检测数据 block 并将特定字节提取到变量中。数据是混合格式,例如字节 4-5 是一个 integerbytes 10-14 是一个 float ,等等。

我编写了一个实验程序来测试从字节 (char) 数组中提取值,但我不理解结果。我的测试程序在运行 Debian Jessie 的 Raspberry Pi 3 上运行。

这是我的程序:

将字节数组转换为部分

#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 使用的类型大小从我打印的 sizeofs 看起来是正确的,那么为什么我的输出只有部分正确? 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 是“短”(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 的强制转换。这不同于从短整数到整数。

更新:由于您询问了“以十六进制形式打印 double 值”。您基本上需要将保存该值的地址解释为十六进制字节数组。例如:

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(或英特尔自己的特定布局)可能会影响浮点的内存字节顺序。

关于使用 memcpy 转换字节数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48495737/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com