2012-03-09 69 views
1

我想這一段代碼就ideone.com,它完全符合,但我無法解釋發生了什麼,任何幫助將是巨大的:)無法理解這個聯盟

這裏是代碼:

#include <stdio.h> 


typedef union { 
    unsigned char*  g_pointer; 
    struct { 
     unsigned short   local_addr; 
     unsigned char   globle_page; 
     } g_l; 
    } Gld_WordType; 


int main() 
{ 
    int Idx; 
    Gld_WordType test; 
    test.g_l.globle_page = 0x13; 
    test.g_l.local_addr = 0xfff0; 

    printf("g_pointer: %x\n 
      local_addr: %x\n 
      globle_page: %x\n", 
      test.g_pointer, 
      test.g_l.local_addr, 
      test.g_l.globle_page); 

    test.g_pointer++;  

    printf("g_pointer: %x\n 
      local_addr: %x\n 
      globle_page: %x\n", 
      test.g_pointer, 
      test.g_l.local_addr, 
      test.g_l.globle_page); 

    return 0; 
} 

結果是:

g_pointer: 13fff0 
local_addr: fff0 
globle_page: 13 
g_pointer: 13fff1 
local_addr: fff1 
globle_page: 13 

如果我簡單地切換的local_addrgloble_page的順序,結果證明是不同勢:

typedef union { 
    unsigned char*  g_pointer; 
    struct { 
     unsigned char   globle_page; // Changed order here. 
     unsigned short   local_addr; // And here 
     } g_l; 
} Gld_WordType; 

這個時候,結果是:

g_pointer: fff00013 
local_addr: fff0 
globle_page: 13 
g_pointer: fff00014 
local_addr: fff0 
globle_page: 14 

OK,這是我這個問題的認識到現在,如果有任何故障,請指出來。

第一,工會在第一實施例由這樣的(這在在globle_page前面local_addr

############ ############# 
#   # #   # 
# g_pointer# # local_addr# 
#   # # MSB or LSB# 
############ ############# 
       ############# 
       #   # 
       # local_addr# 
       # MSB or LSB# 
       ############# 
       ############## 
       #   # 
       # globle_page# 
       #   # 
       ############## 

和佈局是這樣的,如果globle_pagelocal_addr前定義:

############ ############## 
#   # #   # 
# g_pointer# # globle_page# 
#   # #   # 
############ ############## 
       ############## 
       #   # 
       # local_addr # 
       # MSB or LSB # 
       ############## 
       ############## 
       #   # 
       # local_addr # 
       # MSB or LSB # 
       ############## 

所以在情況1(local_addrgloble_page前定義),如果g_pointer的價值chages,local_addr的MSB或LSB也可能發生變化,但爲什麼它實際上是增加一個嗎?因爲我知道我的平臺是Big-Endian字節順序,所以local_addr的MSB應該改變,爲什麼LSB改變了?

的情況2(globle_pagelocal_addr之前定義的),我可以解釋一下g_pointer的值加一,而`globle_page的相應地址「添加一個過,但由於情況1,我不是很肯定的這個。

誰能告訴我這裏發生了什麼確切的答案?如果我沒有正確描述這個問題,對不起我英文不好。

順便說一句,我使用的平臺沒有字節對齊問題。所以結構是按照字節逐字節寫入的。

最好的問候, 盛來運

+0

在哪裏的問題?根據需要,聯合是LSB對齊的,因此向其中的一個添加'1'也會將'1'添加到其他任何其他對象,結構成員的對齊方式實際上是特定於實現的,但編譯器選擇只是做明顯的事情就像你的圖片一樣,第二個例子中的'unsigned char'實際上是一個'unsigned char'加1'unsigned char'填充。 – hroptatyr 2012-03-09 10:52:31

+2

它看起來像標準的小端行爲。你的平臺是什麼?你怎麼知道它是大端的? – 2012-03-09 10:52:47

+0

@Banthar做Embingded C編程,使用宇宙編譯器,和我們使用的微芯片說它的字節順序是Big-Endian – shengy 2012-03-09 10:56:01

回答

1
could anyone tell me the exact answer of what is happening here? 

知道的第一和最重要的是,結果是未定義行爲。您可能會看到不同編譯器的不同結果 - 甚至是使用不同選項的編譯器。最常見的替代行爲是,當您修改一個字段時,其他字段在將來某個時間不會更改。我已經寫了一些測試代碼的形式

// assign to the first field 
// print the second field 
// print the second field 

的過去和第一打印顯示了第二場的前值,而第二打印顯示了第二場的更新值。

直到你真的學習你與問候混淆和不確定的行爲,你應該從未使用union S IN這種方式做的事情。

知道的下一件事就是指針很少1個字節。在大多數現代機器上它們通常是4或8個字節。

瞭解數據佈局接下來的事情是,有時候structs被填充。對於結構

struct { 
    char a; 
    short b; 
}; 

我認爲它只是作爲可能的佈局

<one byte of a> <unused byte> <two bytes of b> 

<one byte of a> <two bytes of b> 

,我會感到意外看到

<one byte of a> <3 unused bytes> <two bytes of b> 

事實上,根據你的實證結果s,我希望你有4個字節的指針,最後的可能性是struct實際上是如何佈局的。

您可以使用sizeofoffsetof功能,以準確確定的東西。 sizeof會告訴你每個類型的長度有多少字節,而offsetof可以讓你確定每個字段開始的結構或聯合中的確切位置。

另一點需要注意的是,指針不是總是佈局像整數。此問題取決於您正在運行的計算機體系結構。不過,我認爲所有「普通」的行爲都會像你期望的那樣。

+0

所以關鍵是這個問題是不確定的行爲? – shengy 2012-03-09 11:01:56

+0

它是實現定義的行爲。 – hroptatyr 2012-03-09 11:12:48

+0

@shengy:這是最重要的*點。但我也給你提供瞭解釋你所看到的信息(特別是你在分析中做錯了什麼)。在實際實現中你會看到最常見的行爲是字段會按照你期望的方式變化,但是當你的程序得到更新的值時是不可預知的(或準可預測的)。 – Hurkyl 2012-03-09 12:20:10

0

進行調查,你可以一個axtra字段添加到工會以檢查其中的成員分佈。

typedef union { 
    unsigned char*  g_pointer; 
    struct { 
     unsigned short   local_addr; 
     unsigned char   globle_page; 
     } g_l; 
    unsigned char all[ sizeof (unsigned char*)]; 
    } Gld_WordType;