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.

Was it helpful?

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top