位移,屏蔽还是位域结构?

我刚开始使用钻头。 我正在尝试使用现有的协议,它可以发送三种不同类型的消息。

类型1是16位结构:

struct digital { unsigned int type:2; unsigned int highlow:1; unsigned int sig1:5; unsigned int :1; unsigned int sig2:7; }; 

前两位(类型,在我上面的结构中)总是1 0。 第三位highlow确定信号是打开还是关闭,sig1 + sig2一起定义信号的12位索引。 该索引在两个字节之间被分割为0,总是在第7位。

类型2是32位结构。 它有一个2位类型,一个10位索引和一个16位值,在位置27,23,15和7处散布着0。一个位字段结构表示forms如下所示:

 struct analog { unsigned int type:2; unsigned int val1:2; unsigned int :1; unsigned int sig1:3; unsigned int :1; unsigned int sig2:7; unsigned int :1; unsigned int val2:7; unsigned int :1; unsigned int val3:7; }; 

sig1和sig2一起形成10位索引。 val1 + val2 + val3一起形成10位索引处的信号的16位值。

如果我理解如何使用前两个结构,我想我可以弄清楚第三个结构。

我的问题是,有没有办法分配一个值,让程序计算出需要进入val1,val2和val3的位?

我已经读过有关位移,位域结构和填充0的内容。 结构似乎是要走的路,但我不确定如何实现它。 我见过的比特打包的例子都没有像这些那样分开的值。 最后,我希望能够创建一个模拟结构,分配一个索引(i = 252)和一个值(v = 32768)并完成它。

如果有人可以建议适当的方法或提供类似样本的链接,我将非常感激。 如果重要,此代码将被合并到更大的Objective-C应用程序中。

谢谢。

布拉德

你可以通过一系列的转换来做,s和/ or s。 我为Type 2完成了10位索引部分:

 unsigned int i = 252; analog a = (analog)(((i << 16) & 0x7f0000) | (i << 17) & 0x7000000); 

本质上,此代码所做的是将int i的10位感兴趣移位到0x7f0000的范围,然后将其与位掩码0x7f0000一起0x7f0000以将位0x7f0000设置为零。 它还将10位的另一个副本移位到0x7000000的范围,然后将其与位掩码0x7000000一起0x7000000以将位0x7000000 and 0x7000000设置为零。 然后它or两个值一起创建所需的零分隔值。

..我不能确定我是否正确计算了位掩码,但我希望你有这个想法。 只需移动,屏蔽和/或合并。

编辑:方法2:

 analog a; a.sig1 = (i & 0x7f); // mask out bit 8 onwards a.sig2 = ((i<<1) & 0x700); // shift left by one, then mask out bits 0-8 

第二个想法方法2更具可读性,所以你应该使用它。

您不应该使用C结构位域,因为位域的物理布局未定义。 虽然您可以弄清楚编译器正在做什么并使您的布局与底层数据相匹配,但如果切换到不同的编译器甚至更新编译器,代码可能无法工作。

我知道这是一种痛苦,但你自己做一点操纵。

您不必这样做,这是union关键字的来源 – 您可以同时指定所有位,或者通过引用具有不同名称的相同位,一次设置它们。