Reputation: 615
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.
Upvotes: 1
Views: 375
Reputation: 206567
Compiler errors/warnings that I see:
;
at the end of the definition of data
.'BM'
is wrong. It needs to be single character.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.
Upvotes: 0
Reputation: 126777
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.
Upvotes: 2