这是我在 Stack Exchange 上的第一个问题,请跟随我。 在我的一个嵌入式 C 项目中,我尝试将结构数据的一部分复制到数组中。 例如:
typedef struct
{
uint16_t Length_ui16;
uint8_t Message_Id_ui8;
uint8_t SensorPosition_ui8;
uint8_t SenType_ui8a[9];
uint8_t SenArticleNo_ui8a[9];
uint8_t SenSerialNo_ui8a[9];
uint8_t SenSoftVer_ui8a[6];
}data;
memcpy(destArr_ui8, &data.SensorPosition_ui8, 34);
说明:我正在尝试从 SensorPosition 开始复制数据(34 字节)。 注意:结构填充和 destArr 大小已考虑在内 代码正在按照我的预期工作。但我的 PC-LINT 在这方面支持了我。
PC-LINT 警告 662:操作符“[”可能创建越界指针(超出数据末尾 33)
我的分析是,PC_LINT认为源只是一个单字节变量(SensorPosition),因此给出33字节的出站警告。
所以,真正的问题是,
我很确定这是未定义的行为;是的,您知道
SensorPosition_ui8
之后会发生什么,但是当您调用 memcpy
时,您专门向该单个成员传递了一个指针,并且您超出了该成员的范围。
即使您认为 UB 在这里并不重要,仍然存在一个问题,即参与
memcpy
的成员之间可能存在填充。这不仅意味着 SensorPosition_ui8
到 SenSoftVer_ui8
占用超过 34 个字节,而且 destArr_ui8
很可能在 memcpy
之后有随机填充字节,而您不知道其位置或值。
我建议在这里使用
union
。除了解决您的问题之外,它还可以使源代码更干净一些。
typedef struct
{
uint16_t Length_ui16;
uint8_t Message_Id_ui8;
union
{
uint8_t Sensor_ui8a[34];
struct
{
uint8_t SensorPosition_ui8;
uint8_t SenType_ui8a[9];
uint8_t SenArticleNo_ui8a[9];
uint8_t SenSerialNo_ui8a[9];
uint8_t SenSoftVer_ui8a[6];
};
};
} data;
// ...
memcpy(destArr_ui8, data.Sensor_ui8a, sizeof data.Sensor_ui8a);