回答
不,這是不可能的。這是因爲缺少C++在二進制級別的標準化。
C++和可移植性
一旦決定要 由分發C++類的(從他的書Essential COM,章COM作爲一種更好的C++報價) DLL,其中一個 面臨着的一個基本問題 C++的弱點,也就是lac k的 標準化在二進制級別。 雖然ISO/ANSI C++草案 工作文件試圖編纂這 程序編譯和什麼運行它們將 是,的 語義效果也沒有試圖規範 的C++二進制運行時模型。該 第一次這個問題將成爲 明顯的是,當一個客戶端嘗試對FastString DLL的導入庫從 一個C++的研究與開發環境等 比一個用於構建 FastString DLL鏈接 。
結構填充由不同的編譯器完成。即使您使用相同的編譯器,根據您使用的pragma pack,結構的打包對齊方式也可能不同。
不僅如此,如果你寫兩個結構,其成員是正是一樣的,唯一的不同的是,在他們聲明的順序是不同的,那麼每個結構的大小可以(而且經常是)不同。
例如,看到這種情況,
struct A
{
char c;
char d;
int i;
};
struct B
{
char c;
int i;
char d;
};
int main() {
cout << sizeof(A) << endl;
cout << sizeof(B) << endl;
}
與gcc-4.3.4
編譯它,你會得到這樣的輸出:
8
12
也就是說,大小即使這兩個結構具有相同的成員有不同的!在Ideone
的底線是,標準不談論填充應該怎麼做,所以編譯器可以自由地做出任何決定,你不能承擔所有的編譯器做同樣的決定。
有'__attribute __((packed ))'我用於共享內存結構以及用於映射網絡數據的結構。它確實會影響性能(請參閱http://digitalvampire.org/blog/index.php/2006/07/31/why-you-shouldnt-use-__attribute__packed/),但它對網絡相關結構非常有用。 (就我所知,這不是一個標準,所以答案依然如此)。 – Pijusn 2015-06-08 07:11:55
我不明白爲什麼struct A的大小是8而不是更多。 { char c; // 那這個呢? char d; // size 1 + padding of 3 int i; // size 4 }; – Dchris 2017-03-03 08:01:28
@Dchris - 編譯器可能很小心地確保每個字段基於自己的自然對齊進行對齊。 c和d是一個字節,因此無論您將它們放在單字節CPU指令的哪個位置,它們都是對齊的。然而,int需要在一個4字節的邊界上對齊,要達到那個邊界需要在d之後填充兩個字節。這讓你到8。 – hoodaticus 2017-05-25 20:58:22
您可以使用類似boost::serialization
之類的東西。
不,沒有安全的方法。除了填充之外,還必須處理不同的字節排序和不同大小的內置類型。
您需要定義一種文件格式,並將結構轉換爲該格式。序列化庫(例如boost :: serialization或google的協議緩衝區)可以幫助解決這個問題。
「結構(或類)的大小可能不等於其成員大小的總和。」 – 2011-03-22 22:21:04
@Thomas:沒錯。這只是開始的樂趣。 – Erik 2011-03-22 22:23:05
長話短說,沒有。沒有平臺無關的標準符合方式來處理填充。
填充被稱爲在標準 「對準」,並且它開始在3.9/5討論它:
對象類型具有對準 要求(3.9.1,3.9.2)。完整對象類型的對齊方式爲 實現定義的整數 表示多個字節的值; 對象分配在地址 ,滿足其對象類型的對齊要求 。
但它從那裏繼續前進,並轉移到標準的許多黑暗角落。對齊是「實現定義的」,這意味着它可以在不同編譯器之間不同,甚至在編譯器的相同下的地址模型(即32位/ 64位)上不同。
除非您有嚴格的性能要求,否則您可能會考慮以不同的格式(如字符串)將數據存儲到光盤。當自然格式可能是其他內容時,許多高性能協議都會使用字符串發送所有內容。例如,我最近處理的低延遲交換饋送發送日期爲格式如下的字符串:「20110321」,時間類似地發送:「141055.200」。儘管此交換饋送整天發送500萬條消息,但它們仍然使用字符串處理所有內容,因爲這樣可以避免排序和其他問題。
如果你有機會自己設計結構,它應該是可能的。基本思想是你應該設計它,這樣就不需要在其中插入填充字節。第二個訣竅是你必須處理差異性。
我將介紹如何使用標量構造結構,但只要您對每個包含的結構應用相同的設計,就應該可以使用嵌套的結構。
首先,C和C++的基本事實是,類型的對齊不能超過類型的大小。如果會,那麼將不可能使用malloc(N*sizeof(the_type))
分配內存。
佈局結構,從最大的類型開始。
struct
{
uint64_t alpha;
uint32_t beta;
uint32_t gamma;
uint8_t delta;
接下來,墊了手動的結構,所以,在年底你將匹配最大的類型:
uint8_t pad8[3]; // Match uint32_t
uint32_t pad32; // Even number of uint32_t
}
下一步是決定是否結構應存放在小或大endian格式。如果存儲格式與主機系統的字節不匹配,最好的方法是在寫入之前或讀取結構之後,在原地10「交換」所有元素。
這聽起來很有趣。但是,您能詳細瞭解一下:爲什麼按照長度遞減的順序排列它,爲什麼要填充它,使得偶數個uint32_t? – Phil 2015-02-21 22:52:15
@Phil,一個基本類型,比如'uint32_t',可以(可能)有一個匹配它的大小的對齊需求,在這個例子中是4個字節。編譯器可以插入填充來實現這一點。通過手動執行此操作,編譯器無需執行此操作,因爲對齊總是正確的。缺點是在對齊要求不太嚴格的系統上,手動填充的結構將比編譯器填充的結構大。您可以按照升序或降序完成此操作,但是如果您按升序執行int,則需要在結構體的中間插入更多墊... – Lindydancer 2015-02-22 08:34:45
...僅在您需要時才需要填充結構體的結尾計劃在數組中使用它。 – Lindydancer 2015-02-22 08:35:13
- 1. C結構填充問題
- 2. 填充C++ POD結構
- 3. C++ - 結構和類填充
- 4. 關於在C++中的結構填充
- 5. C結構中的對齊/填充
- 6. 填充結構
- 7. 結構填充
- 8. 在結構c中填充數組#
- 9. C++填充結構的2D矢量
- 10. c結構的64位對齊/填充?
- 11. 將C++結構填充爲2的冪
- 12. Vb.net用c#填充循環結構#
- 13. 填充結構的大小
- 14. 數據結構填充
- 15. 關於結構填充
- 16. 填充結構更有效
- 17. 使用memcpy填充結構
- 18. 如何填充結構/類
- 19. 使用snprintf填充結構
- 20. 結構填充陣列
- 21. 包結構/避免填充
- 22. 空結構來填充它
- 23. 結構填充解釋
- 24. 如何填充樹結構?
- 25. 用String []填充結構體?
- 26. 通過C++中的文件填充數組或結構體
- 27. 按c中的函數填充typedef結構
- 28. C++使用memcpy填充結構中的矢量
- 29. 如何在結構中聲明填充?
- 30. 在結構中填充字符指針
通過執行二進制I/O獲得的效率(性能)往往不足以證明研究,設計,開發,特別是調試和維護所花費的資金。源代碼應該很容易理解,但並不簡單。 – 2011-03-22 22:24:50