2013-12-20 66 views
2

我不確定Printf語句是否會打印Status?,我猜測它是編譯器相關的,任何人都可以解釋這個設置狀態在最後打印的是什麼?C語言編程中的結構和聯合

#include <stdio.h> 
#include <string.h> 

typedef union { 
struct { 
    unsigned char colour; 
    struct { 
    unsigned char contrast :1; 
    unsigned char density :3; 
    unsigned char depth :1; 
    unsigned char brightness :1; 
    unsigned char saturation :1; 
    unsigned char channel :1; 
} bits; 
} XStruct; 


    unsigned short status; 
} XUnion; 


void main(void) { 
XUnion yunion; 

memset(&yunion, 0x00, sizeof(yunion)); 

yunion.XStruct.contrast = 0xAE; 
yunion.XStruct.bits.density = 0x01; 
yunion.XStruct.bits.depth = 0x02; 
yunion.XStruct.bits.saturation = 0x01; 

printf("Status: %d", yunion.status); 
} 
+5

爲什麼不運行此代碼並親自查看? –

+0

基本?你的意思是它是考試的一部分嗎? –

+3

@sanjeevmk - 因爲運行代碼並查看結果無法告訴您它是否定義良好,實現定義或未定義行爲。 – detly

回答

1

聯合可以具有多種數據類型的變量,但您可以將值分配給其中的一個。

將值賦給一個變量並打印另一個變量會發生什麼?

爲了便於計算,您可以將聯盟視爲內存塊,從地址0開始。該內存塊的大小是本聯盟中使用的最大數據類型的大小。在你的情況下,它將是struct

所以當你給Union中的變量賦值的時候,你會在這個塊中「放」數值。當你打印任何這些成員時,它將打印從聯盟開始的塊的內容,直到你打印的成員的數據類型的大小。

就你而言,你已經打印了變量status。現在,在我的系統unsigned short使用2個字節的存儲。所以在我的系統中,在分配這些值後,它會打印Union的前兩個字節。像你這樣分配值後,該內存塊的前兩個字節是這樣的:

0100 0101 1010 1110 

所以,當我在我的機器上打印status,它打印在十進制0x45ae17838。因此,根據sizeof(unsigned short)

的值,結果會因系統而異,請使用該代碼進行操作,更改指定的值以注意輸出的差異。這樣你會更快地理解。

更新:

位字段的順序,取決於目標平臺的字節序。檢查了這一點:

Big and Little Endian

,然後,這一點:

How Endianness affects bitfield packing

考慮到這一點,這裏的分手你的位域:

1     010 00  1  0 
    line_current_on flags1  battery_ok 

這是直觀的排序(大端)。但我的平臺使用小端的顯示,所以我的編譯器在它看來是

0  1   00 010   1 
     battery_ok   flags1 line_current_on 

是相反。你的結構也一樣。請注意位域是如何在內存中的Voltage成員之前出現的。小尾巴。

+0

@ChrisRow更新答案和解釋。 –

+1

實際上,該標準指定的位域分配要比鏈接http://mjfrazer.org/mjfrazer/bitfields/要少得多。 MSVC不同於GCC分配位域。如果有足夠的努力,我似乎​​記得有可能注意到GCC與Clang不同地分配它們。等等… –

2

在具有8位字節(八位字節)和小端字節排序(如所有x86/x64處理器)的系統上,預期輸出爲17838或十六進制爲45AE

在具有8位字節(八位位組)和大端字節排序的系統上,期望的輸出是44613,或者是十六進制的AE45

對於具有不同大小的字符的系統,輸出很難預測,但幸運的是,如果不是現在不存在的話,這些很少見。

說明:內部結構有一個明確定義的順序,在彼此之後跟隨2個完整的八位字節。因此很顯然,在您的代碼之後,這些將依次包含十六進制值AE45。它們被映射到short上作爲聯合,基本上意味着與另一種類型相同的內存數據的「重新解釋」,並且short由標準定義爲2字節值,這意味着endianness在您讀取時起作用它是這樣 - 是最重要的第一個還是最後一個字節?因此,上述預測結果僅在系統體系結構的這一部分中有所不同。