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

时间:2009-11-25 14:41:33

标签: c objective-c bit-manipulation bit-fields

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

类型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和0处散布0。 7.位字段结构表示形式如下:

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应用程序中。

感谢。

布拉德

3 个答案:

答案 0 :(得分:4)

您可以通过一系列轮班andor来完成。我已经完成了Type 2的10位索引部分:

unsigned int i = 252;

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

本质上,这段代码的作用是将int i中感兴趣的10位移位到16-25的范围,然后使用位掩码and将其0x7f0000设置为位22 - 31到零。它还将10位的另一个副本移位到17-26的范围,然后使用位掩码and将其0x7000000移位以将位0-22和26-31设置为零。然后将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更具可读性,所以你应该使用它。

答案 1 :(得分:1)

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

我知道这很痛苦,但你自己做一点操作。

答案 2 :(得分:0)

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