C语言 在结构中将变量强制转换为半字节

0h4hbjxa  于 5个月前  发布在  其他
关注(0)|答案(1)|浏览(59)

我有一个这样的结构体:

typedef struct 
{
    uint8 nibble_1 : 4;
    uint8 nibble_2 : 4;
    uint8 data_1;
    uint8 data_2;
    uint8 data_3;
} NibbleStruct;

字符串
这是一个用于CAN通信的32位消息。
在代码中,我有以下内容:

...
NibbleStruct nibble_struct;
uint8 nibble_to_assign = 0U;
nibble_struct.nibble_1 = nibble_to_assign;
...


我需要保留GCC(gnu 99)标志-Werror=conversion,但这给出了错误消息:
file_name.c错误:从“uint 8”转换为“unsigned char:4”可能会改变其值[-Werror=conversion]|
我试着用一些

...
nibble_struct.nibble_1 = (uint8:4) nibble_to_assign;
...


...
nibble_struct.nibble_1 = (uint8) nibble_to_assign : 4;
...


但并不奇怪,这并不编译。
有没有办法将变量nibble_to_assign转换为结构体的半字节nibble_1?或者在结构体外部的代码中声明一个半字节。

c0vxltue

c0vxltue1#

建议将“车库标准”uint8删除为ISO C标准uint8_t
这里有几件事要记住:

  • C标准不支持字符类型/uint8_t的位字段-这是一个不可移植的编译器扩展。
  • 因此,非标准位字段成员的类型转换和提升也不包含在C标准中。
  • -Wconversion是一个不稳定的编译器选项,容易出现误报和误导性诊断。它很适合用于压力测试/代码审查,但不应该包含在正常构建中。

在这种情况下,-Wconversion抱怨的问题是,显然不能预测uint8_t值是否适合4位的位字段。
我可以通过强制将未签名的升级到unsigned int来关闭它:

nibble_struct.nibble_1 = nibble_to_assign & 0xFu;

字符串
但是请注意,无论是结构体还是位字段都不是特别适合或推荐用于建模硬件或数据协议。结构体内部可能有填充字节或填充位。如果你坚持使用结构体,你可能必须编写序列化/非序列化例程来避免填充问题。你可能必须这样做来处理endianess,因为CAN通常(但不总是)使用大端。

相关问题