【问题标题】:Should be casting used for setting a bitfield?应该使用强制转换来设置位域吗?
【发布时间】:2019-03-17 10:22:06
【问题描述】:

假设,我有以下结构:

struct my_struct {
    uint32_t bf1 : 3;
    uint32_t bf2 : 5;
    uint32_t bf3 : 16;
    uint32_t bf4 : 8;
};

以及以下枚举:

enum bf1_values {
     Val1 = 0x0;
     Val2 = 0x4;
     Val3 = 0x7;
};

另外,bf1 的 getter 和 setter 函数:

uint32_t bf1_getter() {
    return global_struct.bf1; // cast value to (uint32_t)?
}


void bf1_setter(enum bf1_values val) {
    global_struct.bf1 = val; // cast enum to (uint32_t)?
}

为了安全起见,我应该在 getter 和 setter 函数中使用类型转换吗?

编辑:

结构应该被发送到硬件。

EDIT2:

我想要实现的是真正确定enum 将被正确写入位域,并从位域中正确读取。

【问题讨论】:

  • 类型转换与安全无关,通常恰恰相反。
  • @JoachimPileborg 好的,但是这种代码编写的正常/良好做法是什么?
  • 编译时没有警告吗?然后你不需要铸造。否则必须确保代码是安全的,强制转换对你没有帮助(它只会帮助你关闭编译器警告)。
  • 哦,顺便说一句,如果位域结构要被硬件使用,那么你应该确保它被正确打包(所以任何字段之间都没有填充)。
  • @JoachimPileborg 关于包装,我知道。无论如何,谢谢。

标签: c casting bit


【解决方案1】:

这里不需要强制转换 - 只要符合要求的实现不应该破坏其他成员,分配就已经是“安全的”了。假设应用正常的整数溢出语义,唯一有问题的情况是有符号溢出,这可能会引发一个信号(但如果位域宽度小于完整的位域宽度,我很难在实践中看到这种情况发生将缺少对溢出检测的硬件支持),否则是实现定义的。此警告不适用于您的示例,因为目标类型是无符号的。

请记住,位字段语义在很大程度上是实现定义的——即使使用int 以外的类型实际上也是一种语言扩展——您需要检查编译器是否按照您的期望执行所有操作相关平台。

一种更便携但不太方便的方法是只使用uint32_t 并手动进行位摆弄。如果您不需要这种可移植性,它应该可以按原样进行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-17
    相关资源
    最近更新 更多