[英]Pointer alignment not compatible with MISRA-C 2012
我正在尝试按如下方式转换某个指针:
我有这个结构:
typedef struct {
/** Interface index */
uint8_t if_index;
/** flags */
uint32_t flags; /* error */
/** packet id */
uint32_t packet_id;
/** structure must be aligned to 32 bit */
uint8_t padding[3];
} v2x_tx_indication_value_t;
并尝试执行此转换:
lmac_cv2x_tx_packet_id_t *packet_id_ptr = NULL;
packet_id_ptr = (lmac_cv2x_tx_packet_id_t *)&tx_ind_ptr->packet_id;
此转换不符合 MISRA(根据规则 11.3),因为数据未正确对齐。 我尝试根据以下解决方案对齐地址,但它编译(错误:“表达式必须具有整数类型 C/C++(31)”):
if ((address & 0x3) == 0) {
packet_id_ptr = (lmac_cv2x_tx_packet_id_t *)&tx_ind_ptr->packet_id;
}
如果有人在这里有更好的想法,可以使用一些帮助:)
您根本无法在 C 中进行像这样的野指针转换。 Alignment 不是唯一的问题,还有严格的指针别名和可移植性。
关于对齐/填充,添加uint8_t padding[3];
最后什么也没做——如果那里需要填充,编译器会自动添加它。
你需要重写代码。 这是一种选择:
typedef union
{
lmac_cv2x_tx_packet_id_t stuff;
uint32_t packet_id;
} packet_id_t;
typedef struct {
/** Interface index */
uint8_t if_index;
/** flags */
uint32_t flags; /* error */
/** packet id */
packet_id_t packet;
} v2x_tx_indication_value_t;
不幸的是, union
在其他 MISRA-C 规则中存在问题,但在这种情况下,您将其用于类型双关语,而不是将不相关的数据存储在同一 memory 位置,这是 MISRA-C 禁止union
规则的内容,因此可能存在偏差并且明智的。
从 MISRA-C:2012 修正案 2 中可以看出,使用 C11 匿名联合应该很好。不过,如果它不支持 C11,它可能会使您的 static 分析器感到困惑。 例子:
typedef struct {
/** Interface index */
uint8_t if_index;
/** flags */
uint32_t flags; /* error */
/** packet id */
union // C11 anonymous union
{
lmac_cv2x_tx_packet_id_t stuff;
uint32_t packet_id;
};
} v2x_tx_indication_value_t;
另一种选择是memcpy
。
如前所述,alignment 只是规则 11. 3基本原理的一部分。 实际上,它是关于(禁止)类型双关语的。
据我了解,如果启用了所有MISRA 规则,则无法执行您需要的操作。 但是如果有问题的代码用于有许多不同数据包格式的通信任务,灵活的 header 等,则很可能规则 11. 5 ( “不应执行从指针到 void 到指针到对象的转换” )已经被禁用。
如果是这样,可以使用:
lmac_cv2x_tx_packet_id_t *packet_id_ptr = NULL;
packet_id_ptr = (lmac_cv2x_tx_packet_id_t *)(void*)&tx_ind_ptr->packet_id;
(注意规则 11.3 和 11.4 使用“介于...和...”,规则 11.5 使用“从...到...”)
如果可能的话,我更喜欢使用过渡 void * 指针(如 function 参数或局部变量)来避免级联转换并使代码更具可读性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.