簡體   English   中英

在C中轉儲結構

[英]Dumping struct in C

使用fwrite簡單地將結構轉儲到二進制文件是一個好主意嗎? 例如

  struct Foo {
     char name[100]; 
     double f;
     int bar; 
  } data;

   fwrite(&data,sizeof(data),1,fout);

它有多便攜? 我認為拋出編譯器給出的任何內容(填充,整數大小等等)真是個壞主意。 即使平台可移植性不重要。

我有一個朋友認為這樣做很常見......在實踐中。 這是真的嗎?

編輯:編寫可移植二進制文件的推薦方法是什么? 使用某種庫? 我對如何實現這一點感興趣。(通過指定字節順序,大小,......?)

這當然是一個非常糟糕的主意,原因有兩個:

  • 由於對齊問題和編譯器情緒,相同的struct在不同平台上可能具有不同的大小
  • struct的元素可能在不同的機器上有不同的表示(想想big-endian / little-endian,IEE754與其他一些東西, sizeof(int)在不同的平台上)

無論您希望文件是可移植的還是僅僅是代碼,這都非常重要。

如果你只是想在同一個C實現上讀回數據(這意味着對任何影響結構布局的編譯器選項的值都是相同的),使用相同的結構定義,那么代碼是便攜。 由於其他原因可能是一個壞主意:更改結構的困難,理論上可能存在將填充字節轉儲到磁盤或在該字符串數組中的任何NUL終結符之后的字節的安全風險。 它們可能包含您從未打算堅持的信息。 也就是說,操作系統在交換文件中一直這樣做,所以不管怎樣,但是當用戶注意到你的文檔格式並不總是刪除他們認為已刪除的數據時,請嘗試使用這個借口,他們只是通過電子郵件將其發送給了記者。

如果文件需要在不同的平台之間傳遞,那么這是一個非常糟糕的主意,因為你不小心將文件格式定義為“Win32上的MSVC最終寫入”。 這可能最終在其他平台上讀取和寫入非常不方便,當然,當您在具有不兼容的結構存儲表示的另一個平台上運行時,您首先編寫的代碼將無法執行此操作。

按優先順序編寫可移植二進制文件的推薦方法可能是:

  1. 別。 使用文本格式。 准備好在浮點值中失去一些精度。
  2. 使用圖書館,雖然這里有一點選擇的詛咒。 您可能認為ASN.1看起來很好,只要您自己永遠不必操縱這些東西。 我猜想Google Protocol Buffers相當不錯,但我自己從未使用它。
  3. 根據每個unsigned char的含義來定義一些相當簡單的二進制格式。 這對於字符[*]和其他整數來說很好,但對於浮點類型來說有點棘手。 “這是IEEE-754浮點數的小端表示”,只要您的所有目標平台都使用IEEE浮點數,它就可以。 我希望他們這樣做,但你必須打賭。 然后,組合該字符序列進行編寫並將其解釋為:如果您“幸運”,那么在給定平台上,您可以編寫完全匹配它的結構定義,並使用此技巧。 否則,請執行您需要的任何字節操作。 如果你想要真正可移植,請注意不要在整個代碼中使用int來表示從bar獲取的值,因為如果你在某個平台上執行int ,那么int是16位,那么它就不適合。 而是使用longint_least32_t或其他東西,並在寫入時檢查值。 或者使用uint32_t並讓它換行。

[*]直到你擊中EBCDIC機器,就是這樣。 並不是說任何人都會認真地希望你的文件能夠移植到純文本文件無法移植的機器上。

你是多么喜歡在半夜接聽電話? 使用#pragma打包它們或者按變量寫它們變量。

是的,這種愚蠢是很常見的,但這並不是一個好主意。 您應該按指定的字節順序單獨編寫每個字段,這樣可以避免對齊和字節順序問題,但需要花費一點點額外的工作量。 逐字段讀取和寫入也會使您的軟件升級變得更加輕松,並且必須閱讀舊數據格式或底層硬件架構發生變化。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM