Search code examples
c++fwritefread

Writing variables of different types to binary file and then reading them into class variables gives wrong values


I am trying to create to read from a binary file into variables of a class. The integers are read and displayed correctly but the double gets a weird value. I'm not sure what is happening here. The output of the command windows is:

98
366
7
-9.25596e+61

Here's my code:

#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <vector>

class text
{
private:
    int var1, var2, var3;
    double var4;
public:
    int getVar1() { return var1; }
    int getVar2() { return var2; }
    int getVar3() { return var3; }
    double getVar4() { return var4; }
};

using namespace std;

int main()
{
    // Create test binary file
    FILE* file = fopen("D:\\Desktop\\TestFile", "wb");

    // Define test variables
    int var1 = 98, var2 = 366, var3 = 7;
    double var4 = 52.13;

    // Write test variables to file
    fwrite(&var1, sizeof(var1), 1, file);
    fwrite(&var2, sizeof(var2), 1, file);
    fwrite(&var3, sizeof(var3), 1, file);
    fwrite(&var4, sizeof(var4), 1, file);

    fclose(file);

    // Read from file into class
    FILE* input;
    input = fopen("D:\\Desktop\\TestFile", "rb");
    text t;
    fread(&t, sizeof(t), 1, input);

    cout << t.getVar1() << endl << t.getVar2() << endl << t.getVar3() << endl << t.getVar4() << endl;

    fclose(input);

    return 0;
}

Solution

  • The compiler is allowed to pad your struct, and it does in this case:

    Here's a test to print out the size of 3 ints + the size of 1 double versus the size of an instance of text (demo):

    class text
    {
    private:
     int var1, var2, var3;
     double var4;
    public:
     int getVar1() { return var1; }
     int getVar2() { return var2; }
     int getVar3() { return var3; }
     double getVar4() { return var4; }
    };
    
    int main()
    {
        std::cout << sizeof(int) + sizeof(int) + sizeof(int) + sizeof(double) << " versus " << sizeof(text) << std::endl;
    }
    

    Output:

    20 versus 24

    This happens because the compiler likes to align things (and is free to do so unless you specify otherwise).

    Instead, I suggest you overload the >> operator for text, use std::ifstream, and std::ofstream because you're using C++, and read into the members directly.