我正在从 ARM 微型中的 SD 卡读取值:
Res = f_read(&fil, (void*)buf, 6, &NumBytesRead);
其中fil
是指针,buf
是存储数据的缓冲区。
这就是问题所在:它是一个数组,但我希望将该数组的内容放在一个变量中。
举一个实际的例子:从文件中读取的 6 个字节是:
buf[0] = 0x1B
buf[1] = 0x26
buf[2] = 0xB3
buf[3] = 0x54
buf[4] = 0xA1
buf[5] = 0xCF
我希望有:uint64_t data
等于0x1B26B354A1CF
.也就是说,数组的所有元素"连接"在一个 64 位整数中。
没有类型双关语,你可以执行以下操作。
uint64_t data = 0;
for (int i=0; i<6; i++)
{
data <<= 8;
data |= (uint64_t) buf[i];
}
使用联合,但请记住字节序。
union
{
uint8_t u8[8];
uint64_t u64;
}u64;
Typedef Union{ uint8_t u8[8]; uint64_t U64;}u64;
typedef enum
{
LITTLE_E,
BIG_E,
}ENDIANESS;
ENDIANESS checkEndianess(void)
{
ENDIANESS result = BIG_E;
u64 d64 = {.u64 = 0xff};
if(d64.u8[0]) result = LITTLE_E;
return result;
}
uint64_t arrayToU64(uint8_t *array, ENDIANESS e) // for the array BE
{
u64 d64;
if(e == LITTLE_E)
{
memmove(&d64, array, sizeof(d64.u64));
}
else
{
for(int index = sizeof(d64.u64) - 1; index >= 0; index--)
{
d64.u8[sizeof(d64.u64) - index - 1] = array[index];
}
}
return d64.u64;
}
int main()
{
uint8_t BIG_E_Array[] = {0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80};
ENDIANESS e;
printf("This system endianess: %sn", (e = checkEndianess()) == BIG_E ? "BIG":"LITTLE");
printf("Punned uint64_t for our system 0x%lxn", arrayToU64(BIG_E_Array, e));
printf("Punned uint64_t for the opposite endianess system 0x%lxn", arrayToU64(BIG_E_Array, e == BIG_E ? LITTLE_E : BIG_E));
return 0;
}
这里要注意的事情:
- 正确排序字节
- 将六个字节读入一个 64 位整数
(大字节序(中的字节按主机字节顺序存储到 64 位整数中来解决,例如使用以下两个 marcos:
/* below defines of htonll() and ntohll() are taken from this answer:
https://stackoverflow.com/a/28592202/694576
*/
#if __BIG_ENDIAN__
# define htonll(x) (x)
# define ntohll(x) (x)
#else
# define htonll(x) ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
# define ntohll(x) ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
#endif
问题 2 可以通过多种方式解决:
扩展您的方法
#define BUFFER_SIZE (6) ... assert(BUFFER_SIZE <= sizeof (uint64_t)); uint8_t buffer[BUFFER_SIZE]; FILE * pf = ...; /* open file here */ /* test if file has been opened successfully here */ ... result = f_read(pf, buffer, BUFFER_SIZE, ...); /* test result for success */ uint64_t number = 0; memset(&number, buffer, BUFFER_SIZE) number = ntohll(number);
使用联合使用">类型双关语">
union buffer_wrapper { uint8_t u8[sizeof (uint64_t)]; uint64_t u64; }
而不是
uint8_t buffer[BUFFER_SIZE];
用
union buffer_wrapper buffer;
而不是
memcpy(&number, buffer, BUFFER_SIZE) number = ntohll(number)
用
number = ntohll(buffer.u64)