2013-10-08 37 views
1

让我们假设,我有以下结构:应该铸造用于设置位域?

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; 
}; 
除了

,getter和setter功能BF1:

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函数中的类型转换以确保安全?

编辑:

的结构应该被发送到HW。

EDIT2:

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

+6

型铸造无关安全,往往是完全相反。 –

+0

@JoachimPileborg好的,但是这样的代码写作的正常/好的做法是什么? – Alex

+0

它是否在没有警告的情况下编译?然后你不需要投射。否则*你*必须确保代码是安全的,投射对你没有帮助(它只会帮助你关闭编译器警告)。 –

回答

2

无需铸造在这里 - 在分配已经“安全”的,只要符合的实现不应损坏其他成员。假设正常的整数溢出语义应用,唯一有问题的情况下签署的溢出,从而可以提高的信号(但我很难看到这种事情发生在实践中,如果该位字段宽度是不是一个完整的字作为harware支持度溢出检测将会缺失)并且在其他情况下是实现定义的。此警告不适用于您的示例,因为目标类型未经签名。

记住位字段的语义在很大程度上实现定义 - 即使使用比int其他类型实际上是一种语言的扩展 - 它是由你来检查,编译器做你希望它在所有相关做些什么平台。

更便携,还不太方便的方法是只需使用一个uint32_t,做手工位摆弄。如果你不需要这种可伸缩性,它应该没问题。