I’m trying to read data from a binary file and put it into a struct.
The first few bytes of data.bin are:
03 56 04 FF FF FF ...
And my implementation is:
#include <iostream>
#include <fstream>
int main()
{
struct header {
unsigned char type;
unsigned short size;
} fileHeader;
std::ifstream file ("data.bin", std::ios::binary);
file.read ((char*) &fileHeader, sizeof header);
std::cout << "type: " << (int)fileHeader.type;
std::cout << ", size: " << fileHeader.size << std::endl;
}
The output I was expecting is type: 3, size: 1110, but for some reason it’s type: 3, size: 65284, so basically the second byte in the file is skipped. What’s happening here?
Actually the behavior is implementation-defined. What actually happens in your case probably is, there is a padding of 1 byte, after
typemember of the struct, then after that follows the second membersize. I based this argument after seeing the output.Here is your input bytes:
the first byte
03goes to the first byte of the struct, which istype, and you see this3as output. Then next byte56goes to the second byte which is the padding hence ignored, then the next two bytes04 FFgoes to the next two bytes of the struct which issize(which is of size2bytes). On little-endian machine,04 FFis interpreted as0xFF04which is nothing but66284which you get as output.And you need basically a compact struct so as to squeeze the padding. Use
#pragmapack. But such a struct would be slow compared to the normal struct. A better option is to fill the struct manually as:Another way to write the last line is this:
But this is implementation-defined, as it depends on the endian-ness of the machine. On little-endian machine, it most likely would work.
A friendly approach would be this (implementation-defined):
But again, the last line depends on the endian-ness of the machine.