我正在尝试编写一个C程序来读取一个检测数据块并将特定字节拉出到变量中。数据是混合格式,例如字节4-5是integer
,bytes
10-14浮点数等。
我写了一个实验程序来测试从字节(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
地址: 7EA7E5DB 7EA7E5DA 7EA7E5D8 7EA7E5D6 7EA7E5D0 7EA7E5CC 7EA7E5C0 7EA7E5B8 7EA7E5B4 7EA7E5A8 7EA7E5A0
Little Endian
签名短:FFFF87FF -30721
无符号短语:87FF 34815
签署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
而不是值,因为输出接近上面打印的变量地址。发生了什么事?
答案 0 :(得分:1)
采取以下措施:
memcpy(&i,&v1[30],2);
printf("Signed Short: %04X %hd\n",i,i); // FF 87
将chars和short作为参数传递给变量参数函数(如printf
)将导致这些参数被隐式转换为整数。
i
&#34;简短&#34; (16位)。并且当它传递给printf
时,如果在命中堆栈之前转换为int(32位)。这包括符号扩展。 0xff87是负数(简称)。因此,在打印之前,0xff87会被强制转换为0xffffff87。
作为学习练习,试试这个:
printf("Signed Short: %04X %hd\n",(unsigned short)i,(unsigned short) i); // FF 87
这将强制从短到无符号短整数到整数。这与从短到整数不同。
更新:由于您询问&#34;以十六进制格式打印双精度值&#34;。您基本上需要将保存该值的地址解释为十六进制字节数组。例如:
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(或英特尔自己的特定布局)可能会影响浮点的内存中字节顺序。