2009-11-25 40 views
4

我是新來的工作與位。我試圖使用現有的協議,它可以發送三種不同類型的消息。移位,掩蔽或位場結構?

類型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用0穿插,15 & 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應用程序中。

謝謝。

布拉德

+0

我不確定我能得到你..當你說「val1 + val2 + val3在一起」時,你的意思是連接還是普通加法?如果是串聯,你的問題只是關於如何在給定串聯版本的適當位置插入零? – int3 2009-11-25 14:52:48

+0

它是串聯的。值是一個16位的值,其中的位需要被分成三個「段」。因此,val1保存Value的3個最高有效位,然後是val2的7個位,然後是val3的7個最低有效位。 所以,問題是關於在適當的位置插入0,但是,在模擬結構的情況下,信號索引(非0)也需要插入到值的中間。 謝謝。 – Brad 2009-11-25 15:05:44

回答

4

您可以用一系列的變化,and s和or S的做到這一點。我已經做了10位索引部分2類型:

unsigned int i = 252; 

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

從本質上講,這個代碼是int i感興趣的10位轉移到範圍16 - 25,那麼它and與位掩碼的IT 0x7f0000將位22-31設置爲零。它還將10位的另一個副本移動到範圍17-26,然後它與位掩碼0x7000000一起將位0-22和26-31設置爲零。然後將兩個值一起創建您想要的零分值。

..我不是很確定我是否正確計算了掩碼,但我希望你已經明白了。只需轉移,屏蔽和合並即可。

編輯:方法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是更可讀的,所以你應該使用這個。

0

你不必這樣做,這就是union關鍵字出現的地方 - 你可以同時指定所有的位,或者通過引用相同的位,使用不同的名稱,將它們全部設置爲一旦。

+1

工會不會奇蹟般地讓你把0放在你的位模式中。 – int3 2009-11-25 18:08:37

1

您不應該使用C結構位域,因爲位域的物理佈局未定義。雖然你可以弄清楚你的編譯器正在做什麼,並讓你的佈局與底層數據相匹配,但如果你切換到不同的編譯器甚至更新你的編譯器,代碼可能無法正常工作。

我知道這是一種痛苦,但要自己動手操作。

+1

在某些情況下,使用位域解析消息是完全合理的。例如,在程序與DSP芯片功能密切相關的嵌入式應用中,沒有理由擔心可移植性,因爲平臺更改會破壞所有內容。弄清楚編譯器如何處理位域,並利用它可以讓你編寫更清晰的代碼。 – AShelly 2009-12-03 19:44:38

+0

也許我錯過了一些東西,但添加了__attribute __((packed));在結構的大括號之後應該保留排序和大小,以防止編譯器搞亂你的結構。 – Warpling 2011-12-07 00:18:58