2014-02-13 38 views
-1

我遇到了一些聯盟中的數據對齊問題,我似乎無法弄清楚。使用與下面類似的聯合,聯盟的基地址似乎有一些數據偏移。聯盟成員數據對齊

typedef union MyUnion 
{ 
    struct MyStruct 
    { 
     uint16_t val_1; 
     uint8_t val_2; 
     uint8_t val_3; 
    }data; 
    uint8_t data_array[4]; 
}MyUnion; 

在某些時候,我在與數據填充結構,

my_union.data.val_1 = 65535; 
my_union.data.val_2 = 0; 
my_union.data.val_3 = 0; 

然後我嘗試使用數組來訪問數據。我期望在數組的基地址處看到的是val_1的第一個字節,255。但是,當訪問數組中的數據時,它似乎偏離了結構的基數1個字節。

printf("Bytes of struct: %#08x\n", my_union.data.val_1); 
printf("Bytes of array: %#08x\n", my_array.data_array[0]); 

無論什麼樣的價值觀,我把在輸出上述結果與此類似。

Bytes of struct: 0x00ffff 
Bytes of array: 0x0000ff 

我首先想到的是,會員可在某種程度上抵消並引用不同的內存地址的,但是當我打印的地址,它們是相同的。

此外,如果我打印下面的值他們是平等的。

printf("Bytes of struct: %#08x\n", my_union.data); 
printf("Bytes of array: %#08x\n", *(my_array.data_array - 1)); 

輸出:

Bytes of struct: 0x00ffff 
    Bytes of array: 0x00ffff 

我敢肯定,我失去了一些東西簡單,但我無法弄清楚,此刻。感謝您提前提供任何幫助。

+1

你應該會得到錯誤。發佈sscce,而不是代碼片段。 – this

+1

如何與下面的「類似」是你實際使用的聯盟?你真的可以用你在問題中展示的聯盟重現問題嗎?你能展示編譯的完整但最少的代碼及其產生的輸出,並確定你正在運行它的編譯器和平臺嗎?您選擇的值對於診斷問題並不是很好;您應該考慮將(例如)0xFEDC分配給'val_1',也許將0xBA分配給'val_2',將0x89分配給'val_3'。請參閱MCTRE/MCVE [如何創建一個最小,完整,測試和可讀的示例](http://stackoverflow.com/help/mcve) –

+0

@JonathanLeffler它是相當不同的,結構包含一些奇怪的數據類型,即位字段結構,但是工會中結構的第一個成員是一個無符號短整型。我正在使用MinGW GCC 4.6.2。該平臺是Altera的RISC軟核處理器,稱爲Nios II。對不起,關於示例中的值。我使用了其中可以分別跟蹤字節的數據,並顯示了上面的行爲。數組數據始終與結構數據偏移一個字節。 – dsell002

回答

0

這是明確錯誤:

printf("Bytes of array: %#08x\n", my_array.data_array); 

要打印的,而不是內容,這是什麼,似乎你感興趣的數組的第一個元素的地址。無論如何,打印一個指針應該使用%p格式,所以一個不錯的編譯器應該給你一個警告。

要打印數組的內容,您必須打印它的每個元素。 uint8_t(而不是unint8_t!)的正確格式說明符是宏PRIx8

0

嘗試little-endian的機器上這個

printf("Bytes of struct: %#08x\n", *(uint32_t*)&my_union.data); 
printf("Bytes of array: %#08x\n", *(uint32_t*)my_union.data_array); 
+2

請在代碼中加入一些解釋。 – rgettman

1

運行(英特爾酷睿i7的Mac OS X 10.9.1小牛,GCC 4.8.2),下面的程序:

#include <inttypes.h> 
#include <stdio.h> 

typedef union MyUnion 
{ 
    struct MyStruct 
    { 
     uint16_t val_1; 
     uint8_t val_2; 
     uint8_t val_3; 
    } data; 
    uint8_t data_array[4]; // NB: was unint8_t!!! 
} MyUnion; 

int main(void) 
{ 
    MyUnion my_union; 

    my_union.data.val_1 = 0xFEDC; 
    my_union.data.val_2 = 0xBA; 
    my_union.data.val_3 = 0x98; 

    printf("val_1 = 0x%.4" PRIX16 "; val_2 = 0x%.2" PRIX8 "; val_3 = 0x%.2" PRIX8 "\n", 
      my_union.data.val_1, my_union.data.val_2, my_union.data.val_3); 

    char const *pad = ""; 
    for (size_t i = 0; i < sizeof(my_union.data_array); i++) 
    { 
     printf("%sarray[%zu] = 0x%.2" PRIX8, pad, i, my_union.data_array[i]); 
     pad = "; "; 
    } 
    putchar('\n'); 

    return 0; 
} 

產生如下輸出:

val_1 = 0xFEDC; val_2 = 0xBA; val_3 = 0x98 
array[0] = 0xDC; array[1] = 0xFE; array[2] = 0xBA; array[3] = 0x98 

這是我所期望的。你會在一個大型機器上得到不同的輸出(除英特爾以外的任何東西,或多或少)。

您需要修改此代碼(或類似的東西)以展示您認爲自己擁有的任何問題,並顯示修改後的代碼和實際輸出以及您對期望內容的理解以及您對不同輸出的期望。

+0

這正是我期望看到的。我也跑過了這個數組,並且我得到了相同的字節偏移量。我也看到了你的其他評論。我會在那裏回覆它。謝謝。 – dsell002