rzi*_*ler 1 c variable-assignment compiler-flags compiler-warnings nibble
我面临以下情况。我有一个这样的结构:
typedef struct
{
uint8 nibble_1 : 4;
uint8 nibble_2 : 4;
uint8 data_1;
uint8 data_2;
uint8 data_3;
} NibbleStruct;
Run Code Online (Sandbox Code Playgroud)
背景信息:它是用于 CAN 通信的 32 位消息。
在代码中我有以下内容:
...
NibbleStruct nibble_struct;
uint8 nibble_to_assign = 0U;
nibble_struct.nibble_1 = nibble_to_assign;
...
Run Code Online (Sandbox Code Playgroud)
我需要保留 GCC (gnu99) 标志-Werror=conversion,但这会给出错误消息:
file_name.c 错误:从 'uint8' 转换为 'unsigned char:4' 可能会改变其值 [-Werror=conversion]|
我尝试用类似的东西进行投射
...
nibble_struct.nibble_1 = (uint8:4) nibble_to_assign; // invalid code
...
Run Code Online (Sandbox Code Playgroud)
和
...
nibble_struct.nibble_1 = (uint8) nibble_to_assign : 4; // invalid code
...
Run Code Online (Sandbox Code Playgroud)
但对于这不能编译并不感到惊讶。
有什么方法可以将我的变量转换为结构的nibble_to_assign 半字节吗?nibble_1或者在结构体外部的代码中声明一个半字节。
建议将“车库标准”uint8改为ISO C 标准uint8_t。
这里有很多事情需要记住:
uint8_tC 标准不支持字符类型/的位字段- 这是不可移植的编译器扩展。-Wconversion是一个不稳定的编译器选项,容易出现误报和误导性诊断。它非常适合用于压力测试/代码审查,但不应该包含在正常构建中。在这种情况下,抱怨的问题-Wconversion是显然无法预测该uint8_t值是否适合 4 位位字段。
我可以通过强制执行未签名的促销来使其安静unsigned int:
nibble_struct.nibble_1 = nibble_to_assign & 0xFu;
Run Code Online (Sandbox Code Playgroud)
但请注意,结构体和位域都不是特别适合或推荐用于建模硬件或数据协议。结构内部可能存在填充字节或填充位。如果您坚持使用该结构,则可能必须编写序列化/反序列化例程以避免填充问题。无论如何,您可能必须这样做才能处理字节序,因为 CAN 最常见(但并非总是)使用大字节序。