Reading a file in struct (C ++)

I am trying to read data from a binary file and put it in a structure. First few bytes data.bin:

03 56 04 FF FF FF ...

And my implementation:

#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 this type: 3, size: 1110, but for some reason it is type: 3, size: 65284, so basically the second byte in the file is skipped. What's going on here?

+5
source share
4 answers

Actually, behavior is determined by implementation. It is likely what actually happens in your case, there is a space of 1 byte, after a typemember of the structure, then the second term follows size. I based this argument after looking at the output.

Here are your input bytes:

03 56 04 FF FF FF

03 , type, 3 . 56 , , 04 FF , size ( 2 bytes), 04 FF 0xFF04, , 66284, .

, . #pragma. . :

char bytes[3];
std::ifstream file ("data.bin", std::ios::binary);
file.read (bytes, sizeof bytes); //read first 3 bytes

//then manually fill the header
fileHeader.type = bytes[0];
fileHeader.size = ((unsigned short) bytes[2] << 8) | bytes[1]; 

:

fileHeader.size = *reinterpret_cast<unsigned short*>(bytes+1); 

, . , , .

( ):

std::ifstream file ("data.bin", std::ios::binary);
file.read (&fileHeader.type, sizeof fileHeader.type);
file.read (reinterpret_cast<char*>(&fileHeader.size), sizeof fileHeader.size);

.

+7

, . , , 4 8 .

pragma compiler. . Visual studio /Zp

, 56 char, n , 2 . 2- , 2 . short '04 FF ', ( ) 0xff04, 65284.

+1

pad , 2 4, . #pragma, , , (, ). .

- , , , , , . , , pragma pack, . , , , - .

C, , , : , ,

, #pragma pack (1) , , , , , , , . , , ; , , C : , :

void readStruct(header &h, std::ifstream file)
{
    file.read((char*) &h.type, sizeof(char));
    file.read((char *) &h.size, sizeof(short));
}

( , , )

, ++, - , myObject.readData(file). ?

Easier to read, maintain, compile, leads to faster and more optimized code, by default.

I usually don't like messing with the #pragma directives if I'm not sure what I'm doing. The consequences may be surprising.

0
source

You can use the #pragma packcompilation directive to override the fill problem:

#pragma pack(push)
#pragma pack(1)
struct header {
    unsigned char type;
    unsigned short size;
} fileHeader;
#pragma pack(pop)
0
source

All Articles