2013-03-28 7 views
2

我讀簡單的二進制數據,而不會指針,使用C++類沒有填充:最好的方法用下面的代碼讀取C二元數據++使用類沒有填充

#include <fstream> 
#include <iostream> 

using namespace std; 

class Data { 
    public: 
    int a; 
    int b; 
    short int c; 
    double d; 
}__attribute__((packed)); 

int main() { 
    Data myData;  
    ifstream ifs("test.bin", ios::binary); 
    ifs.read((char *)&myData, sizeof(myData)); 
    ifs.close(); 
} 

我使用這種方法,因爲數據可能有20多種不同的格式,我想寫20多個不同的類來覆蓋可能出現的所有格式。我還讀到其他選項包括使用位字段,編譯指示,甚至是boost序列化例程(我不能,因爲我必須使用std)。我的問題是:這是使用沒有填充的類讀取簡單二進制數據的最佳方式?你建議有其他的選擇嗎?我想了解什麼是最安全和最廣泛使用的方法。

+2

幾乎沒有其他方式同樣簡單而有效。至少不是我所知道的。爲了好看,只需調用'Data''struct'即可。 – Aneri

+2

你的方法很好。你可以考慮['#pragma pack(push,0)'](http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html),讓你的代碼被更多的編譯器支持。儘管這兩種方法都不能保證被C++支持。 –

+0

德魯,這實際上解決了我的問題,我試圖找到一種編譯器,跨平臺,安全的東西。那麼pragma_pack更安全嗎?你能再詳細一點嗎? –

回答

1

我用這些宏允許包裝結構編譯的GCC和VC:

#ifdef _MSC_VER 
    #define BEGIN_PACK __pragma(pack(push, 1)) 
    #define END_PACK __pragma(pack(pop)) 
#else 
    #define BEGIN_PACK 
    #define END_PACK __attribute__((packed)) 
#endif 

,那麼你會使用它們像這樣:

BEGIN_PACK 
struct Data { 
    int a; 
    int b; 
    short int c; 
    double d; 
} END_PACK; 

但是,是的,這是通常是如何完成的。請注意,這些是非標準擴展。

C++ 11已經定義了打包指令,但我不知道它們是否被編譯器支持。

+0

「__attribute __((packed))」僅適用於gcc嗎? –

+1

是的。鏗鏘也支持它,因爲它是gcc兼容的。但是,是的,這是一個gcc擴展。 – mfontanini

+0

某些編譯器具有'pshpackX.h'和'poppack.h'頭文件,其中'N'是所需的字節對齊方式(1,2,4,8等),以隱藏編譯器特定的細節。 –

2

通常,人們會使用struct而不是class,但是,同樣的概念適用於兩者。

+0

感謝您的回答,但您確定使用結構而不是類更好嗎?我在C++中讀到,推薦使用類來保持一致。我還讀到,類和結構之間的主要區別在於默認情況下,類是默認私有的,而結構默認是公共的。 –

+2

@JaimeCervantes我見過的常見約定是,當所有公共成員都是可變的,並且沒有使用getter或setter時,通常使用'struct'而不是'class'。 – andre

相關問題