Question

I have the need of writing the data contained in a struct to a binary file.

Lets say given the struct of

struct data {
unsigned char sig;
int reserved;
}

I want to be able to simply output the contents of this struct to a file.

I have tried to use this

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();

I expected the output would be (in hex, using a 32 bit compiler(so ints are 4 bytes)):

42 4D 00 00 00 00

But this is not what is printed.

Can someone explain why this is not working and the steps necessary to fix it?

Thanks.

Était-ce utile?

La solution

First of all, 'BM' is two bytes, and cannot be fit into a single unsigned char ('BM' is probably treated by your compiler as a multibyte literal, which is probably not what you want).

Then, the compiler is free to add padding inside a structure to align it to the correct word boundaries; on x86 correct members aligment guarantees much better read performances, on other architectures if the alignment is wrong you get a hardware exception.

In your case, for example, on 32-bit x86 the binary layout of your struct will be one byte of sig, three bytes of padding, and then the reserved int (that will be aligned on 4-byte boundaries for optimal access speed).

There's no standard way to avoid padding; you have to resort to compiler-specific tricks. On VC++, you'll have to use #pragma pack, supported also on g++ and clang, although their "native" way is to use __attribute__(packed).

By the way, if you have to write a "portable" file format to file (like the DIB you are trying to write) always use fixed-size integer types (from stdint.h) and be ready to deal with endianness issues if you plan to port to other architectures.

Autres conseils

Compiler errors/warnings that I see:

  1. Missing ; at the end of the definition of data.
  2. Assinging 'BM' is wrong. It needs to be single character.
  3. Assigning NULL to data.reserved. You should make it:

    data.reserved = 0;
    

If you want to minimize the space taken by the file on disk, write each field of the struct separately.

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

Another thing I noticed is that you are opening your file with the flag ios::app. It appends to an existing file. Is that what you mean? If not, you can remove that flag.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top