提问人:Ciuboss 提问时间:11/13/2023 更新时间:11/13/2023 访问量:104
在两个字节上写入 uint8 变量?
Writing a uint8 variable on two bytes?
问:
所以有点奇怪,因为我正在使用一个我无权访问的界面。但它的要点是这样的:我有一个 16 字节、16 个 uint8 元素的数组。前 12 个元素非常具体,这意味着对于 array[0] 和数组1,我个人给出了具体的值,而接下来的 10 个元素,我需要复制另一个数组的元素。我遇到的问题是数组的最后 4 个元素,基本上是最后 4 个字节。在我的“图表”中,我有这样的东西:
如图所示,它说 index 和 ID 不像具有 2 个 uint8 元素的数组,它们看起来像是一个变量,每个变量占用 2 个字节。然而,问题在于,为了获取 index 和 ID 的值,我使用了我之前讨论过的接口,并且该接口接受 uint8* 值。所以我不确定我应该做什么。 我是否应该声明 uint8 类型的索引和 ID 并将它们传递到这个函数中,它们将获得某个值,然后使用按位运算符将其放在 2 个字节上?我的代码实现如下所示:
uint8 FinalArray[16];
uint8 index;
uint8 ID;
uint8 buffer[10];
FinalArray[1] = 0x01;
FinalArray[2] = 0x10;
//I do some data manipulation for buffer here, does not matter
memcpy(&FinalArray[2], buffer, sizeof(buffer));
//and here I am unsure of how I should proceed
Get_IndexAndID(&index, &ID);
//the function returns just 1 or 0 in case it was successful or not, so I guess I need to pass the variables by reference for them to change value inside the function itself
//I also got a hint that inside this function, both index and ID get values because they are the "destination" inside a memcpy function, but I am not sure if this changes the way they are passed or what
//is this even doing what I am thinking of?
FinalArray[12] = index & 0xFF;
FinalArray[13] = (index >> 8) & 0xFF;
FinalArray[14] = ID & 0xFF;
FinalArray[15] = (ID >> 8) & 0xFF;
Any help, additions or corrections to my code would be really welcome. Thanks!
答:
根据您的图表,它可以是:struct
struct diagram {
uint8 v01;
uint8 v10;
uint8 buffer[10];
uint16 index;
uint16 ID;
};
union bigbuf {
uint8 array[16];
struct diagram diagram;
};
根据您用于放入 (即 )的代码,它们每个为 16 位。所以,他们应该是而不是index
ID
FinalArray
<<
uint16
uint8
C 数组是“原点 0”而不是“原点 1”。所以,而不是:
FinalArray[1] = 0x01;
FinalArray[2] = 0x10;
你想要:
FinalArray[0] = 0x01;
FinalArray[1] = 0x10;
重构代码:
union bigbuf bigbuffer;
uint8 buffer[10];
struct diagram *dia = &bigbuffer.diagram;
dia->v01 = 0x01;
dia->v10 = 0x10;
// manipulate buffer ...
// copy buffer into struct ...
buffer[0] = 1;
memcpy(dia->buffer,buffer,10);
// get index and ID
Get_IndexANDID(&dia->index,&dia->ID);
现在事情已经完全填满了。
我们可以将所有数据直接放入结构中,而无需额外复制:
union bigbuf bigbuffer;
struct diagram *dia = &bigbuffer.diagram;
dia->v01 = 0x01;
dia->v10 = 0x10;
// manipulate buffer directly ...
uint8 *buffer = dia->buffer;
buffer[0] = 1;
// get index and ID
Get_IndexANDID(&dia->index,&dia->ID);
现在的大多数系统都是“little-endian”,所以上面的代码[可能]可以工作。
有限数量的系统(有些仍在使用)是“大端序”的。
因此,如果您不确定,可以按“网络字节顺序”存储数据,该顺序始终为“big-endian”:
union bigbuf bigbuffer;
struct diagram *dia = &bigbuffer.diagram;
dia->v01 = 0x01;
dia->v10 = 0x10;
// manipulate buffer directly ...
uint8 *buffer = dia->buffer;
buffer[0] = 1;
// get index and ID
Get_IndexANDID(&dia->index,&dia->ID);
// convert to network byte order
dia->index = htons(dia->index);
dia->ID = htons(dia->ID);
当收到这样的“数据包”时,我们需要反转这一点:
// receive packet from network ...
// convert to native/host byte order
dia->index = ntohs(dia->index);
dia->ID = ntohs(dia->ID);
评论
__attribute__((packed))
sizeof(struct diagram) == 16
static_assert(sizeof(struct diagram) == 16, "Strange struct diagram"):
这可能是一个错别字
FinalArray[1] = 0x01;
FinalArray[2] = 0x10;
因为索引从 C 语言开始。0
您需要知道接口所需的字节序。
void bigEndian(uint8_t *array, uint16_t val)
{
array[0] = val >> 8;
array[1] = val;
}
void littleEndian(uint8_t *array, uint16_t val)
{
array[1] = val >> 8;
array[0] = val;
}
uint8_t *formArray(uint8_t *array, const uint8_t *buffer, const uint16_t index, const uint16_t ID, int endianess)
{
array[0] = 0x1;
array[1] = 0x10;
memcpy(array + 2, buffer, 10);
if(endianess)
{
bigEndian(array + 12, index);
bigEndian(array + 14, ID);
}
else
{
littleEndian(array + 12, index);
littleEndian(array + 14, ID);
}
return array;
}
评论