天天看點

missing closing parenthesis at end of #pragma

環境為Tornado2.2,VxWorks5.5

編譯出現警告如下:

warning: missing closing parenthesis at end of #pragma

warning: Unrecognised value for #pragma pack directive.

warning: malformed `#pragma pack'

有問題的代碼如下:

<b>#ifndef</b> _CFE_

<b>#pragma</b> pack(1)

<b>#endif</b>

<b>typedef</b><b>struct</b> _ROBO_PORT_CTRL_STRUC

{

    <b>unsigned</b> <b>char</b>   rx_disable;

    <b>unsigned</b> <b>short</b>   tx_disable;

} ROBO_PORT_CTRL_STRUC;

<b>#pragma</b> pack()

問題出在編譯的預處理指令#pragma上,在C語言中,預處理指令#pragma pack(n)是負責确定結構類型資料結構體内各個變量在記憶體中位址對齊方式的,第一、如果n大于等于結構體中長度最大的變量所占用的位元組數,那麼偏移量必須滿足預設的對齊方式,第二、如果n小于該變量的類型所占用的位元組數,那麼偏移量為n的倍數,不用滿足預設的對齊方式。結構的總大小也有個限制條件,分下面兩種情況:如果n大于所有成員變量類型所占用的位元組數,那麼結構的總大小必須為占用空間最大的變量占用的空間數的倍數;否則必須為n的倍數。更加詳細的内容請自己Google之。

對于本例來說,如果設定了#pragma pack(1),則:

sizeof(ROBO_PORT_CTRL_STRUC) = 3

如果沒有設定#pragma pack(1),則:

sizeof(ROBO_PORT_CTRL_STRUC) = 4

一般情況下使用編譯器預設的對齊方式即可,但是總有些例外情況需要設定#pragma pack()參數,但是設定完了以後,想要恢複到原來預設的對齊方式怎麼辦?因為Tornado實際上使用的是GCC編譯器,是以查找了一下GCC的幫助,原文如下(中文是我自己的翻譯):

1、#pragma pack(n) simply sets the new alignment.

#pragma pack(n),就是設定新的對齊方式為n

2、#pragma pack() sets the alignment to the one that was in effect when compilation started (see also command-line option -fpack-struct[=n] see Code Gen Options).

#pragma pack(),将對齊方式恢複為原來的初始值(可以參見指令行編譯選項-fpack-struct[=n])

3、#pragma pack(push[,n]) pushes the current alignment setting on an internal stack and then optionally sets the new alignment.

#pragma pack(push[,n]),将目前的對齊方式存入内部堆棧,然後設定新的對齊方式為n

4、#pragma pack(pop) restores the alignment setting to the one saved at the top of the internal stack (and removes that stack entry). Note that #pragma pack([n]) does not influence this internal stack; thus it is possible to have #pragma pack(push) followed by multiple #pragma pack(n) instances and finalized by a single #pragma pack(pop).

#pragma pack(pop),恢複堆棧内儲存的對齊方式,需要注意的是,單獨使用#pragma pack([n])指令它隻設定新的對齊方式,而不會把目前對齊方式放入堆棧。可以用#pragma pack(push)指令将目前的對齊方式入棧,然後再使用#pragma pack([n])指令設定新的對齊方式,最後使用#pragma pack(pop)恢複原來的設定。

從上面的說明可以總結出如下的幾種配對使用方式,并附上在Tornado2.2,VxWorks5.5的環境下的編譯結果:

使用方法

編譯結果

1

#pragma pack(push)

#pragma pack(1)

……

#pragma pack(pop)

有警告,發生在#pragma pack(pop)那一行,内容如下:

missing closing parenthesis at end of #pragma

Extraneous characters at end of #pragma pack

Unrecognised value for #pragma pack directive.

malformed `#pragma pack'

2

#pragma pack(push,1)

有警告,發生在#pragma pack(push,1)和#pragma pack(pop)這兩行,内容同上

3

#pragma pack()

有警告,發生在#pragma pack()那一行,内容同上

4

有警告,發生在#pragma pack(push,1)和#pragma pack()這兩行,内容同上

上表的運作結果說明如下:

運作結果說明

#pragma pack(1)指令起作用,後續結構體定義按照新的對齊方式進行對齊,而#pragma pack(pop)不起作用,後續的結構體依然按照#pragma pack(1)的方式對齊

#pragma pack(push,1)不起作用,依然按照預設方式對齊。

#pragma pack(1)指令起作用,後續結構體定義按照新的對齊方式進行對齊,而#pragma pack()不起作用,後續的結構體依然按照#pragma pack(1)的方式對齊

從上面兩張表可以看出,不管是哪種組合方式,都有編譯警告,而且都沒有真正達到設定和恢複對齊方式的目的,但是這也就是網上所能找到的最多的解決方案了。 

經過多次試驗和研究,終于發現使用#pragma pack(0)就沒有編譯錯誤,而且可以實作恢複預設的對齊方式。

最後聲明,本解決方案是在Tornado2.2 + VxWorks5.5下編譯測試通過,其它環境沒有測試,上述結果僅供參考。

本文轉自 tywali 51CTO部落格,原文連結:http://blog.51cto.com/lancelot/832909,如需轉載請自行聯系原作者