我有一个字节数组:
uint8_t* data = 10101010 01000001 00000000 00010010 00000000 00000010..........
uint8_t get_U8(uint8_t * data, int* offset)
{
uint8_t tmp = *((uint8_t*)(data + *offset));
*offset += sizeof(uint8_t);
return tmp;
}
uint16_t get_U16(uint8_t* data, int* offset)
{
uint16_t tmp = *((uint16_t*)(data + *offset));
*offset += sizeof(uint16_t);
return tmp;
}
偏移量是2。
get_U8(data, 0) = 10101010 = 170 ===> OK
get_U8(data, 1) = 01000001 = 65 ===> OK
get_U8(data, 2) = 00000000 = 0 ===> OK
get_U8(data, 3) = 00010010 = 18 ===> OK
但是
get_U16(data, 2) = 4608 ===> NOT OK (should be 18)
4608 = 00010010 00000000
所以我知道2个字节是反转的。
我不明白为什么get_U16
会反转字节的位置,这不是大字节序/小字节序的问题,因为这是前8位与8秒倒置的结果。
我只是期望uint16_t
在给定位置取16位,然后在此处返回18。
有人可以告诉我我在做什么错吗?
答案 0 :(得分:3)
我不明白为什么get_U16会反转字节的位置,这不是大字节序/小字节序的问题,因为这里是前8位和8秒倒置了。
这是不正确的。字节顺序考虑较大数据类型中字节的顺序。在这种情况下,最低有效字节似乎存储在最低地址。
当您为p
读取索引2的地址(称为uint16_t
)时,该地址处的内存包含该值的低字节。地址p + 1
包含该值的高字节。
答案 1 :(得分:2)
您应该手动处理所有事情。
uint8_t get_U8(uint8_t * data, int* offset)
{
uint8_t tmp;
# I think the following should work even on systems where `sizeof(uint8_t) != 1`
memcpy(&tmp, &((unsigned char*)data)[*offset], sizeof(uint8_t));
*offset += sizeof(uint8_t);
return tmp;
}
uint16_t get_U16(uint8_t* data, int* offset)
{
uint8_t tmp1 = get_U8(data, offset);
uint8_t tmp2 = get_U8(data, offset);
uint16_t tmp = tmp1 << 16 | tmp2;
# or tmp = tmp2 << 16 | tmp1; depending on the endianess you want to have
return tmp;
}
正在做
uint16_t tmp = *((uint16_t*)(data + *offset));
不好,对于您*offset +=
手动移动的缓冲区非常不好。如果data + *offset
未对齐uint16_t
,则很容易引起不确定的行为(读作:分段错误)。不要这样您想要两个字节中的uint16_t
吗?逐字符读取char并使用移位和仅移位。
这不是大字节序/小字节序的问题,因为这里是前8位与8秒倒置的
简而言之:正是确切耐力的原理。它将前8位转换为后8位。
任何人都可以告诉我我做错了什么吗?
您没有做错任何事情,您的代码可能会按原样工作。