2012-04-12 50 views
2

我不知道爲什麼,但位字段分配不能按預期方式工作。可能只是一個愚蠢的事情,但我一直無法找到問題。位字段結構賦值意外行爲

任何幫助都是值得歡迎的。

typedef struct a { 
    unsigned char a1 :1; 
    unsigned char a2 :3; 
    unsigned char a3 :2; 
    unsigned char a4 :2; 
} __attribute__((packed)) mystruct; 

int main() { 
    mystruct d; 
    d.a1 = 0; 
    d.a2 = 2; 
    d.a3 = 1; 
    d.a4 = 2; 

    unsigned char *val = (unsigned char*) &d; 

    printf("%02X \n", *val); 
    printf("%02X \n", sizeof(hola)); 

    exit(0); 
} 

返回的輸出:

94 
01 

預期輸出:

26 
01 
+2

位字段的預期結果通常不是您所期望的。而不是檢查你的所有代碼,我會問,你是否考慮過你的平臺的所有字節碼? – KevinDTimm 2012-04-12 16:49:58

+2

0x94是正確的。你爲什麼期望0x26? – James 2012-04-12 16:50:37

+0

@詹姆斯,如果順序是先MSB後跟LSB它將是0x26 – keety 2012-04-12 16:52:28

回答

8

幾乎一切關於位字段定義實現。特別是單位中的位數的順序。

(C99,6.7.2.1p10)「的單元(高階到低階或低階到高階)內的位域的分配順序是實現定義的」。

在您的實現中,首先將位存儲在單元lsb(最低有效位)中,而不是像您期望的那樣先存儲在msb(最高有效位)中。

你有什麼是:

[a1.0] [a2.0] [a2.1] [a2.2] [a2.0] [a3.1] [a4.0] [a4.1] 
    0  0  1  0  1  0  0  1 
bit 0      -      bit 7 

lsb      -      msb 

這是0x94,如果你認爲最左比特是最顯著位。

+0

我喜歡我的評論比你的回答更好 - 即使你的回答是正確的:) – KevinDTimm 2012-04-12 16:50:53

+1

@KevinDTimm如果你認爲你的評論更好,將其作爲回答 – ouah 2012-04-12 16:58:08

+0

我之所以這樣說的原因是因爲我想讓他自己弄清楚 - 但我也喜歡你的答案,因爲答案對使用位字段的人來說通常不是很明顯,你很好地感謝他通過這個過程 - 榮譽&upvote(同時,我的評論不是'大'足以回答 - 沒有足夠的信息) – KevinDTimm 2012-04-12 17:00:56

8

ASCII藝術:

MSB        LSB 
+----+----+----+----+----+----+----+----+ 
|a4.1|a4.0|a3.1|a3.0|a2.2|a2.1|a2.0| a1 | 
+----+----+----+----+----+----+----+----+ 
| 1 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 
+----+----+----+----+----+----+----+----+ 
|  0x9  |  0x4  | 
+----+----+----+----+----+----+----+----+ 

如前所述,該行爲是實現定義;這是組織數據的兩種合法方式之一,並且似乎是您的機器上選擇的格式。另一種行爲是。

MSB        LSB 
+----+----+----+----+----+----+----+----+ 
| a1 |a2.2|a2.1|a2.0|a3.1|a3.0|a4.1|a4.0| 
+----+----+----+----+----+----+----+----+ 
| 0 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 
+----+----+----+----+----+----+----+----+ 
|  0x2  |  0x6  | 
+----+----+----+----+----+----+----+----+ 

這顯然是你期望的行爲。

由於它是實現定義的,因此編譯器必須記錄它的行爲,您可以查看手冊並查找編譯器執行的操作。

如果您有可移植性擔心,您需要考慮如何組織結構定義以按照您需要的方式在您使用的每個平臺上工作。

+0

注意,對於這個特定點,例如「gcc」是指單位內的位域分配的ABI:*順序(C90 6.5.2.1,C99 6.7.2.1):由ABI確定「* http: /gcc.gnu.org/onlinedocs/gcc/Structures-unions-enumerations-and-bit_002dfields-implementation.html – ouah 2012-04-12 18:31:58

+0

您的回答非常完整...非常感謝! – jlanza 2012-04-13 05:46:00