如何在bitfield结构中输入常量字段

时间:2016-04-03 19:04:02

标签: c struct unions bit-fields

以下是结构的示例:

typedef struct {
   int8 SSPM:4;
   int8 CKP:1; 
   int8 SSPEN:1; 
   int8 SSPOV:1;
   int8 WCOL:1; 
} sspcon_layout;

(1)如何在此结构中创建任意位长度的常量值,例如如何在CKP和SSPEN之间有两个高位?

(2)如果结构未与字节边界对齐,我如何找出最终结构应该如何?例如,如果我有一个9位长的结构,最后一个字段是1位长,它会进入第二个字节的MSB还是LSB?

(3)另外,如果最后一个字段长4位并在第一个和第二个字节之间分割怎么办?这4位字段的2 MSB是否与所有编译器下的前2位连续或者它们会被分开吗?

我正在使用CCS PIC C编译器。

2 个答案:

答案 0 :(得分:1)

封闭结构中位域的顺序未在标准中定义,严格依赖于底层架构。

即。大/小Endian和定义位0(MSB或LSB)

这使得位字段的结构不可移植。

如果字段的总和大于(使用的字段类型的大小),则struct将转换为内存中的下一个sizeof()字节。

这意味着,

如果使用uint8_t,则每个结构将是1的倍数。

如果使用unsigned int,那么每个struct都将是sizeof(int)bytes的倍数。

这意味着,如果对字段类型使用unsigned int并且sizeof(int)为4,则结构可以保存32位。

如果结构长度为32位且定义的位数仅为25位,则还没有定义结构的哪一端将包含未定义的位字段。

答案 1 :(得分:-1)

  

(1)如何在此结构中创建任意位长度的常量值,例如如何在CKP和SSPEN之间有两个高位?

你没有这样做。除了所有其他考虑因素之外,结构定义(例如您提供的结构定义)仅描述结构成员的类型和顺序,而不描述其值。您可以在结构中声明一个const位字段,但它在该结构的任何给定实例中的值将取决于相应的初始化程序(或缺少初始化程序)。

此外,实现在选择结构布局的细节方面具有很大的自由度。以下是一些特定于位域的规定:

  

实现可以分配足够大的任何可寻址存储单元来保存位字段。如果剩余足够的空间,则紧跟在结构中的另一个位字段之后的位字段将被打包到相同单元的相邻位中。如果剩余的空间不足,则是否将不适合的位域放入下一个单元或重叠相邻单元是实现定义的。单元内的位域分配顺序(高阶到低阶或低阶到高阶)是实现定义的。可寻址存储单元的对齐未指定。

(C2011 6.7.2.1/11)

  

(2)如果结构未与字节边界对齐,我如何找出最终结构应该如何?例如,如果我有一个9位长的结构,最后一个字段是1位长,它会进入第二个字节的MSB还是LSB?

仅当struct的值为CHAR_BIT时,您才能拥有9位长的9,因为每种类型的表示形式都具有以位为单位的倍数CHAR_BITCHAR_BIT的值不能小于8.我不知道使用CHAR_BIT与8不同的任何实现。您可能有一个只有9位的结构用来代表会员'值,但几乎肯定会在成员之间或最后,或两者都有填充。详细信息由实施决定,总体规模也是如此。

在各种实现中,看到整体大小为32位,64位,甚至多达128位,我不会感到惊讶,因为某些实现对所有结构应用了4字节或更大的对齐(因此大小)要求类型。另一方面,您可能只看到16位,并且您可能能够通过特定于实现的方式(例如#pragma和编译选项)来影响这些细节。

由于结构布局的许多方面都依赖于实现,如果您真的想要预测结构的布局,那么您最好的办法是查阅您所针对的C实现的文档。依赖这些细节当然是不可移植的,并且首先可能会或可能不会记录细节。作为最后的办法,您可以检查实践中产生的布局,以确定您的实现是如何进行的,但这比预测值具有更多的诊断价值。

  

(3)另外,如果最后一个字段长4位并在第一个和第二个字节之间分割怎么办?这4位字段的2 MSB是否与所有编译器下的前2位连续或者它们会被分开吗?

标准没有规定,并且它没有任何理由相信不同的编译器在这方面会表现一致。实际上,我不确定你如何确信宽度不超过8位的给定位域实际上会在结构表示中分成两个字节。

总的来说,虽然目前还不清楚你在这里做了什么,但我倾向于认为你解决问题的方法是不合适的。在某种程度上,您似乎对编译器的一致性有一些兴趣,我对该评估非常有信心。如果您需要管理位数组的详细信息,那么将作为位数组(在整数,字节数组或其他内容中) 类型)。在这方面,您可能会发现定义用于操作零件的函数或宏非常方便。