用c++编写一个二进制结构

write a struct in binary in c++

本文关键字:一个 二进制 结构 c++      更新时间:2023-10-16

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

假设给定的结构

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位编译器(所以int是4个字节)):

42 4D 00 00 00 00

但这不是印刷出来的。

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

谢谢。

首先,'BM'是两个字节,不能放在一个unsigned char中(编译器可能会将'BM'视为多字节文字,这可能不是您想要的)。

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

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

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

顺便说一句,如果您必须将"可移植"文件格式写入文件(如您试图写入的DIB),请始终使用固定大小的整数类型(来自stdint.h),并且如果您计划移植到其他体系结构,请准备好处理端序问题。

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

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

    data.reserved = 0;
    

如果要最大限度地减少文件在磁盘上占用的空间,请分别写入结构的每个字段。

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

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