2015-11-20 201 views
62

我在最近一次關於C++結構體字段對齊的問題中被問到過,並且理論上C和C++遵循相同的結構打包策略。C vs C++結構對齊

Hovewer,這是錯誤的假設。面試官說,總的來說,C和C++以不同的方式打包結構,我們不應該期待相反的結果。恕我直言,這是奇怪的聲明。對於在C++中用於雙語C/C++頭文件的結構,沒有pack "C"限定符。

因此實際上可能意味着您不能在C++中創建結構並將其傳遞到C庫,因爲通常它的字段將以不同方式對齊並具有不同的偏移量。但事實上,大多數程序員在將指針轉換爲C結構體時,嚴重依賴於這種互操作性,以便用一些輔助方法來引用C++包裝器。你能否澄清這件事?

+13

多麼奇怪的問題。如果C和C++之間的結構填充不同,我會被擰緊。也許面試官在一些晦澀難懂的編譯器中發現了一些非常奇怪的問題 - 或者他正在考慮C和C++編譯器如何可能完全不同,並且期望兩個編譯器以相同填充方式以相同方式對齊字段可能不是我們應該做的事情有信心依賴(但是即使在兩個C編譯器或兩個C++編譯器之間也是如此 - 與語言無關)。 –

+17

你是對的。包裝是一個處理器實現細節,它確保了對齊規則的遵守。針對相同處理器的C編譯器和C++編譯器必須處理相同的實現細節。 –

+1

結構對齊取決於編譯器級別,取決於處理器體系結構。由於ABI要求,編譯器最喜歡在一個套件(GCC,Clang/LLVM)中具有兼容的對齊,但彼此之間可能有不同的規則。 – myaut

回答

68

C和C++語言標準都沒有對struct padding做任何要求,並將其留作編譯器實現細節。對此的嚴格解釋意味着不能保證兩者之間的結構是相同的。但是,實際上,如果需要,給定版本的具有C和C++(例如GCC或Clang)的工具鏈可以以相同的方式打包相同的結構體。如果沒有這個,世界上很多生產代碼根本無法工作。這是工具鏈給出的保證,然而,不是的語言。

值得一提的是,如果你要聲明一個類似結構的C原,倒是訪問說明符(privatepublicprotected),該佈局會改變,但是這是一個有點誇張,因爲結構不再是完全相同的。

+1

是的,如果你添加虛擬功能,它也會有所不同。類似的是相似的。 – SergeyA

+0

注意:重新讀你的文字。你有一些重複的文字。 – Olaf

+0

如果在C++中有隱藏的字段,那麼這些可以是不同的,例如用於虛擬功能和RTTI。 – Olaf

29

這顯然是錯誤的(在面試官方面)。很明顯,對於任何與處理結構的低級別API一起工作的人(例如網絡API),C和C++的struct packing是相同的。所有這些都是C函數,它們接受'C'結構,但從C++代碼安全地被稱爲每天數百萬次。

你應該很幸運,你有這個問題。這表明你不應該在那裏工作。

+9

我喜歡這個答案(雖然我也喜歡另一個),作爲一個實際的,當之無愧的安慰。聽起來好像面試官在他頭腦中有這個奇怪的概念,而不是他試圖讓人們用這種超級理論的方式來思考語言標準假設 - 主要是因爲這部分:*「C和C++的打包結構不同我們不應該期待相反的情況。「*這聽起來不像是面試官堅定地掌握了他所說的話。這是我所期望的一種面試問題...... –

+0

......基於迷信的奇怪編碼標準。至少我見過這種類型。也許我太苛刻了。 –

+5

是的,沒有好的答案壞的問題,應該很高興不在那裏工作 –

4

當開發C++時,開發人員發現C程序員依賴於C++開發人員不想保證的一些東西,但不保證它們意味着許多C代碼也是有效的C++代碼。在用作C++代碼時會被破壞。不可取。

這就是爲什麼他們發明了「POD」結構:沒有使用任何C++特性的結構在C++程序中的行爲與在C程序中的行爲完全相同(除了實現定義的行爲可能會改變的事實之外,一個C編譯器和一個C++編譯器顯然不是同一個實現,另一方面,C++編譯器可能只是從C編譯器複製實現定義)。

如果您使用任何普通的C結構(也是有效的C++結構)(例如,沒有名稱爲「class」的成員),然後您只需在左大括號後面添加「public:」,那麼它的佈局,順序會員,對齊等都可以改變。即使所有結構成員默認都是公共的,所以沒有任何改變。除了因爲「公衆:」它不再是POD。

+0

你爲什麼這麼認爲?當然,所有公衆成員(以及所有私人成員,就此而言)的一個例子就是POD。 – SergeyA