我想union 和 struct 是一個很好用的語法
不過小細節最好還是要弄清楚一點比較好
以下做了一下點這方面的比較
以C30的compiler 為例
ex1:
以這樣的範例來說,應該不會有人有問題吧
union {
unsigned int word;
struct _field_1
{
unsigned int a:5;
unsigned int b:4;
unsigned int c:7;
}field_1;
}union_int_1;
假設
union_int_1.field_1.a=0x1;
union_int_1.field_1.b=0x1;
union_int_1.field_1.c=0x1;
那麼
union_int_1.word 會等於0x0221;
沒錯
這是我們要的答案
ex2:
union {
unsigned int word;
struct _field_2
{
unsigned char a:5;
unsigned char b:4;
unsigned char c:7;
}field_2;
}union_int_2;
假設
union_int_2.field_2.a=0x1;
union_int_2.field_2.b=0x1;
union_int_2.field_2.c=0x1;
那麼
union_int_1.word 會等於0x0101;
沒錯
這不是我們想要的答案,這樣就會出現問題了
問題出在,因為結構的關系,當要做bit field 的設定時,field a 與field b 2者超過8個bit (1個byte),那麼compiler 會自動利用16個bit(1個word)做處理。
所以,這次compiler 對於這個struct 會產生 3個byte 出來,對於union 來說,只能mapping 到2個byte,但多出來的1個byte 就獨自使用了
如果今天不使用到union_int_1.word 這樣的用法時,是不會產生bug,但如果不注意的話,肯定會花一段時間找bug (因為我就是過來人= =)
ex3:
union {
unsigned int word;
struct _field_3
{
unsigned char a:4;
unsigned char b:4;
unsigned char c:8;
}field_3;
}union_int_3;
假設
union_int_3.field_3.a=0x1;
union_int_3.field_3.b=0x1;
union_int_3.field_3.c=0x1;
那麼
union_int_1.word 會等於0x0111;
這也會是我們要的答案
有了上面的實驗結果,那麼我們是不是可以把bit field 的宣告都設為unsigned int (16bit) 這樣就好了
當然沒有錯,是可以都這樣使用,但如果你要做聯結的動作只有unsigned char (8bit) 那就會有另一個課題了
ex4:
union {
unsigned char byte;
struct _field_4
{
unsigned char a:4;
unsigned char b:4;
}field_4;
}union_int_4;
ex5:
union {
unsigned char byte;
struct _field_5
{
unsigned int a:4;
unsigned int b:4;
}field_5;
}union_int_5;
有興趣的可以比較2者所做的結果,這裡所做的結果都會一樣,但是在compiler的時後 ex5 會比 ex4 還要多浪費1個byte ,如果當老闆在和你要求code size 和 ram size 時,你就知道又要準備被釘了= =
PS:小細節不可馬虎,太重要了