用c ++编写二进制结构

时间:2014-04-20 01:40:19

标签: c++ binaryfiles

我需要将结构中包含的数据写入二进制文件。

让我们说给出

的结构
struct data {
unsigned char sig;
int reserved;
}

我希望能够简单地将此结构的内容输出到文件中。

我试过用这个

fstream out("C:\\somepath", ios::out | ios::app | ios::binary);
data writedata;
writedata.sig = 'BM';
writedata.reserved = NULL;
out.write((char*)&writedata, sizeof(writedata));
out.close();

我预计输出会是(十六进制,使用32位编译器(所以整数是4个字节)):

42 4D 00 00 00 00

但这不是印刷品。

有人可以解释为什么这不起作用以及修复它所需的步骤吗?

感谢。

2 个答案:

答案 0 :(得分:2)

首先,'BM'是两个字节,并且不能适合单个unsigned char'BM'可能被编译器视为多字节文字,这可能不是什么你想要的。)

然后,编译器可以自由地在结构中添加填充以使其与正确的字边界对齐;在x86上,正确的成员aligment保证了更好的读取性能,在其他架构上如果对齐错误则会出现硬件异常。

在您的情况下,例如,在32位x86上,结构的二进制布局将是sig的一个字节,三个字节的填充,然后是reserved int (它将在4字节边界上对齐以获得最佳访问速度)。

没有标准的方法可以避免填充;你必须采用特定于编译器的技巧。在VC ++上,你必须使用#pragma pack,也支持g ++和clang,尽管它们的“原生”方式是使用__attribute__(packed)

顺便说一句,如果你必须将“可移植”文件格式写入文件(就像你想写的DIB一样),总是使用固定大小的整数类型(来自stdint.h)并准备好处理如果您计划移植到其他架构,则会出现字节序问题。

答案 1 :(得分:0)

我看到编译器错误/警告:

  1. ;的定义末尾缺少data
  2. 分配'BM'是错误的。它需要是单一字符。
  3. NULL分配给data.reserved。你应该做到:

    data.reserved = 0;
    
  4. 如果要最小化磁盘上文件占用的空间,请分别编写结构的每个字段。

    out.write((char*)&writedata.sig, sizeof(writedata.sig));
    out.write((char*)&writedata.reserved, sizeof(writedata.reserved));
    

    我注意到的另一件事是您使用标记ios::app打开文件。它附加到现有文件。你是这个意思吗?如果没有,您可以删除该标志。

相关问题