2015-11-02 56 views
5

我對如何在struct中排序字節有點困惑。結構中的字節順序

比方說,我有以下結構:

struct container { 
    int myint; 
    short myshort; 
    long mylong; 
}; 

現在,我要初始化struct container類型的變量,就像下面,除了做到使用數組它,我

struct container container1 = {.myint = 0x12345678, 
           .myshort = 0xABCD, 
           .mylong = 0x12345678}; 

假設sizeofintlong4,那的short2

假設沒有填充。

那麼struct10 bytes的佈局如何呢?

它取決於字節順序嗎?

將它像:

0x12345678 ABCD 12345678 

或類似:

0x78563412 CDAB 78563412 

我想要做的是:我有以下的字符數組:

char buffer[10] = {0}; 

我想手動用數據填充該陣列,然後memcpystruct

我應該做[1]

buffer[0] = 0x12345678 & 0xFF; 
buffer[1] = 0x12345678 >> 8 & 0xFF; 
buffer[2] = 0x12345678 >> 16 & 0xFF; 
buffer[3] = 0x12345678 >> 24 & 0xFF; 
... 
buffer[9] = 0x12345678 >> 24 & 0xFF; 

還是應[2]

buffer[0] = 0x12345678 >> 24 & 0xFF; 
buffer[1] = 0x12345678 >> 16 & 0xFF; 
buffer[2] = 0x12345678 >> 8 & 0xFF; 
buffer[3] = 0x12345678 & 0xFF; 
... 
buffer[9] = 0x12345678 & 0xFF; 

我做之前,我memcpy像:

memcpy(&container1, buffer, sizeof(container1); 

而且,如果我是wr到一個數組並複製到struct,它是否跨系統可移植,特別是關於字節序?

編輯: 在大端確實有點endian機器和[2][1]工作?

+5

不,這是不可移植。是的,這取決於排序。而有關填充和類型大小的假設也會導致可移植性問題。 – user3386109

+0

爲了強調*不可移植的方式*,這意味着在同一個操作系統上從編譯器到編譯器都不是可移植的方式,從操作系統到操作系統的便攜性更小。 –

+0

當然這取決於字節順序!在「沒有填充」假設之後,問題不再與結構類型有關。它只是關於在內存中表示整數。 – AnT

回答

2

它取決於字節順序嗎?

是的,它取決於機器的字節順序。所以你的邏輯會根據機器的字節順序而改變。

還有沒有便攜的方式*這樣做是因爲結構填充。雖然不同的編譯器確實提供了禁用結構填充的自定義方法。檢查Force C++ struct to not be byte aligned

  • 您可以添加一個static_assert(需要C11支持)剛好以確保您的代碼不會編譯除非你的結構是排列緊密。你不會有可移植的代碼,但你仍然可以確定,如果你的代碼編譯,它會表現正確。

    static_assert(sizeof(container) == sizeof(int) + sizeof(short) + sizeof(long)); 
    
+0

不同編譯器提供的禁用結構填充的方法不可移植 - 每個編譯器都有自己的方法,除非它正在模擬其他方面的兼容性。您可能需要注意'static_assert'需要一個C11編譯器(或符合C99或C90的編譯器中的非標準擴展)。 –

+0

@JonathanLeffler我已經提到過,在我的回答以及我已經鏈接的問題的答案中,提到OP尋求的解決方案不可移植。編輯以進一步強調它。 – bashrc

+2

我在C語言問題中混合了關於鏈接到僅用於C++的問題的觀點。這至少是一個警告標誌。 –

1

還有一個問題,你的結構元素內對齊的。

您的結構有缺口用於對齊。真正的佈局是,如果你做的事:關於使用union

struct container { 
    int myint; 
    short myshort; 
    char __pad__[2]; // padding to align mylong to 4/8 byte boundary 
    long mylong; 
}; 

什麼:

union { 
    struct container vals; 
    char buf[10]; 
}; 

但是,爲什麼做你想做的事嗎?對於我能想到的幾乎任何場景,可能都有更清晰的方法來獲得效果。

當你說數組,你的意思是你想要初始化你的結構數組嗎?這是可以做到:

struct container conts[3] = { 
    { .myint = 1, .myshort = 2, .mylong = 3 }, 
    { .myint = 4, .myshort = 5, .mylong = 6 }, 
    { .myint = 7, .myshort = 8, .mylong = 9 } 
}; 

BTW,有的方式在C++做static_assert

// compile time assertion -- if the assertion fails, we will get two case 0:'s 
// which will cause the compiler to flag this 
#define static_assert(_assert) \ 
    do { \ 
     switch (0) { \ 
     case (_assert): \ 
      break; 
     case 0: \ 
      break; \ 
     } \ 
    } while (0) 
+0

而不是'char buf [10];',更好的使用'char buf [sizeof(struct container)];'。 – alk