2017-10-14 82 views
2

我知道在C語言中,struct成員的順序是它們聲明的順序加上(通常除非另有說明)否則可能發生填充,導致我創建的兩個第一個結構體他們各自的大小:在C語言中訂購優勢的結構成員

struct MyStructV1 
{ 
    int a; 
    char c; 
    int b; 
}; 

printf("size of MyStructV1 is:%lu \n",sizeof(struct MyStructV1)); // prints 12 

struct MyStructV1Packed 
{ 
    int a; 
    char c; 
    int b; 
}__attribute__((__packed__));; 

printf("size of MyStructV1Packed is:%lu \n",sizeof(struct MyStructV1Packed)); // prints 9 

到目前爲止好。

那麼,我的問題是,下面的MyStructV2的「解壓縮」版本聲明與第一版​​MyStructV1相比有什麼優點/好處嗎?

struct MyStructV2 
{ 
    int a; 
    int b; 
    char c; 
}; 

printf("size of MyStructV2 is:%lu \n",sizeof(struct MyStructV2)); // prints 12 as well 

請注意,現在成員的順序有變化(b在c之前聲明)。

我指的是內存訪問「成本」或週期需要完成,以讀/寫結構成員和/或任何其他相關的考慮因素?

它是依賴於編譯器/架構(如果有的話)?

乾杯,

蓋伊。

+2

大多數並不重要,在所有的時間。您可能希望在較短的區域之前放置更廣泛的區域。當然這取決於體系結構和ABI –

+1

它依賴於編譯器。除此之外,一個非常好的經驗法則是不要擔心打包結構,除非你有一些體系結構和編譯器特定的理由來這樣做,並確切知道它是什麼。否則,讓編譯器處理它並在它認爲合適的地方插入一個或兩個填充符會更好。 –

回答

4

第一個和最後一個版本之間應該沒有什麼區別。在這兩個結構中,int成員都按字邊界對齊,因此可以高效地從內存中讀取它們。它們之間的唯一區別是填充範圍在cb之間,在MyStructV1之間,結尾在MyStructV2之間。但是由於填充沒有執行開銷;訪問結構成員只需通過向結構開頭的地址添加一個已知的偏移量即可完成。在MyStructV1中,b的偏移量是8MyStructV24

+3

這不是100%的事實。特別是如果我們考慮結構包裝。在許多平臺上進行打包涉及字節訪問,甚至可以阻止程序正常工作。例如:外設需要字或半字訪問,但結構已打包並且是字節訪問。包裝被初學者過度使用,應小心使用 –

+0

@ PeterJ_01問題在於比較*不使用包裝的兩種結構。包裝可以產生性能點擊是正確的。 – Barmar

1

如果char小於int然後int(通常是這樣),則結構MyStructV1可以小於MyStructV2。

根據環境(體系結構和編譯器選項),struct MyStructV1可以封裝一個pad或可以不對齊b。 根據體系結構的不同,如果b未加載,它可能需要更多的cpu時鐘。

此外,根據架構的不同,讀取a可以加載更多的內容以立即可用,如果存在填充項,則此優點將減少或丟失。

+0

非常非常差和不準確的答案。國際海事組織,你應該刪除它 –

+0

恕我直言,這是一個簡短的正確答案,我希望它是有用的人。 無論如何,如果你有不同的意見請詳細說明。 –

0

這更有趣,當然還有訂購事宜。

struct aaa1{ 
    char a; 
    char a1; 
    int b; 
}; 

struct aaa2{ 
    char a; 
    char a1; 
    char a2; 
    int b; 
}; 

struct aaa3{ 
    char a; 
    char a1; 
    char a2; 
    char a3; 
    int b; 
}; 

struct aaa4{ 
    char a1; 
    char a2; 
    char a3; 
    int b; 
    char a; 
}; 

int main(void) { 

struct aaa5{ 
    char a; 
    int b; 
    char a1; 
}; 


    printf("%zu %zu %zu %zu %zu %zu\n", sizeof(struct aaa), sizeof(struct aaa1), sizeof(struct aaa2), sizeof(struct aaa3), sizeof(struct aaa4), sizeof(struct aaa5)); 

輸出:8 8 8 8 12 12