将变量转换为结构体中的半字节

问题描述 投票:0回答:1

我面临以下问题。我有一个这样的结构:

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 (gnu99) 标志

-Werror=conversation
但这会给出错误消息:

file_name.c 错误:从“uint8”转换为“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
吗?或者在结构体外部的代码中声明一个半字节。

c casting variable-assignment can-bus nibble
1个回答
1
投票

建议删除“车库标准”

uint8
而采用ISO C标准
uint8_t

这里有很多事情需要记住:

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

在这种情况下

-Wconversion
抱怨的问题是,显然无法预测
uint8_t
值是否适合 4 位位字段。

我能够通过强制将未签名的促销活动静音到

unsigned int

nibble_struct.nibble_1 = nibble_to_assign & 0xFu;

但请注意,结构体和位域都不是特别适合或推荐用于建模硬件或数据协议。结构内部可能存在填充字节或填充位。如果您坚持使用该结构,则可能必须编写序列化/反序列化例程以避免填充问题。无论如何,您可能必须这样做才能处理字节序,因为 CAN 最常见(但并非总是)使用大字节序。

© www.soinside.com 2019 - 2024. All rights reserved.