2015-06-18 21 views
1

我有指定爲以下如何覆蓋C編譯器對齊字大小可變以struct到字邊界

  • 成員1,16位
  • 會員2,32位
  • 會員3的結構, 32位

我將從文件中讀取。我想直接從文件讀入結構。

的問題是,C編譯器將調整變量M1,M2和M3到字邊界,其在32位,因爲我上了ARM Cortex M3工作爲以下結構聲明:

typedef struct 
{ 
    uint16_t m1; 
    uint32_t m2; 
    uint32_t m3; 
}something; 

直接從文件中讀取將以m2和m3爲單位輸入錯誤的值,並讀取2個額外的字節。

我已經破解四周,我目前使用的工作只是正常的情況如下:

typedef struct 
{ 
    uint16_t m1; 
    struct 
    { 
     uint16_t lo; 
     uint16_t hi; 
    }m2; 
    struct 
    { 
     uint16_t lo; 
     uint16_t hi; 
    }m3; 
}something; 

然而,這看起來像一個非常骯髒的黑客。我不禁要求一種更簡潔的方式來強制編譯器用不同的詞語來表達m2和m3的一半,然而這可能是次優的。

我正在使用arm-none-eabi-gcc。我知道有關打包,但無法解決此優化。

編輯:原來我不知道足夠有關bit-包裝:d

+0

你的意思是你的編譯器贏得'讓你把結構聲明爲包裝? –

+0

'arm-none-eabi-gcc'與'packed'屬性一起工作得非常好(除非編譯了一些奇怪的設置,我猜...)。那麼,也許一些古代版本不是... –

+0

雖然我知道指定每個字段的位數,但我完全不知道打包的屬性。不奇怪,我不知道它,因爲我有點害怕__attribute()__ s。哦,這似乎工作得很好 – TSG

回答

3

你在找什麼是packed屬性。這將迫使gcc不對成員做任何填充。從GCC Online docs採取:

填充

該屬性,連接到一個枚舉,結構或聯合類型的定義,指定的最小所需存儲器被用於表示類型。 爲struct和union類型指定此屬性等同於在每個結構或聯合成員上指定packed屬性。在行上指定-fshort-enums標誌等效於在所有枚舉定義上指定packed屬性。

您只能在枚舉定義的關閉大括號後面指定此屬性,而不是在typedef聲明中,除非該聲明也包含enum的定義。

所以,你想的是一樣的東西:

typedef struct 
{ 
    uint16_t m1; 
    uint32_t m2; 
    uint32_t m3; 
} __attribute__ ((packed)) something; 

此外,我會建議使用compile time assertion check,以確保結構的大小真的是你希望它是什麼。

0
__attribute__ ((aligned (2))); 
+0

根據GCC文檔:*對齊的屬性只能增加對齊;但您可以通過指定打包來減少它。* – missimer

1

您不能直接從文件中讀取這樣的結構,而且您不應該嘗試。misalignement可能會導致某些架構陷阱,你不應該依靠編譯指示來解決這個問題。

幾乎(*)的可移植方式,如果要將文件元素讀入結構元素,除非您確定結構體是用相同的體系結構和對齊方式(至少兼容)編寫的,因爲它們用於讀取。

所以對你的使用情況,我建議:

fread(&something.m1, sizeof(something.m1), 1, fd); 
fread(&something.m2, sizeof(something.m2), 1, fd); 
fread(&something.m3, sizeof(something.m3), 1, fd); 

(*),因爲它假定有沒有它可以正確與否取決於你的需求端問題,它幾乎攜帶。如果你在一臺單獨的機器或一個單一的體系結構,它是好的,但是如果你在一個大型機器上寫結構並在一個小型機器上讀取它,會發生壞事......

+0

此代碼專門用於此目標體系結構。它是爲特定的嵌入式系統而構建的,所以我不會預料到任何這樣的問題。字節順序在這裏不是問題。鑑於MCU的字節順序,編譯器將管理字節序。如果你能指點我可以找到有用的潛在「陷阱」的地方。 – TSG