Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Binary Writing/Reading on 32bit to/from 64bit

If you have a binary output stream, and write integers to a file on a 32-bit Windows computer. Would you then be able to read the same integers from that same file on a 64-bit Windows computer?

My guess would be no. Since an integer on a 32-bit computer is 4 bytes, where an integer on a 64-bit computer is 8 bytes.

So does the following code work, while the files have to be able to be read and written from and by both 64-bit and 32-bit computers, no matter the OS, computer architecture and data type. If not how would one be able to do that, while the files have to be in binary form.

Writing

std::ofstream ofs("example.bin", std::ios::binary);

int i = 128;
ofs.write((char*) (&i), sizeof(i));

ofs.close();

Reading

std::ifstream ifs("example.bin", std::ios::binary);

int i = 0;
ifs.read((char*) (&i), sizeof(i));

ifs.close();
like image 980
vallentin Avatar asked Dec 23 '13 00:12

vallentin


1 Answers

While int is 4 bytes on almost all modern platforms (32bit and 64bit), there is no guarantee for its size. So for serializing data into a file or other binary streams, you should prefer fixed width integer types from the header <cstdint> which were introduced in C++11 (some compilers support it in C++03):

#include <cstdint>

...
int32_t i = 128;
ofs.write((char*)(&i), sizeof(i));
...

Another option is to enforce a certain type to have a certain size, e.g. int to have size 4. To make sure your program won't compile if this was not true, use static_assert:

...
int i = 128;
static_assert(sizeof(i) == 4, "Field i has to have size 4.");
ofs.write((char*)(&i), sizeof(i));
...

While this sounds stupid considering we have fixed width integers as above, this might be useful if you want to store a whole struct of which you made assumptions in a certain version of some library. Example: vec4 from glm is documented to contain four floats, so when serializing this struct, it's good to check this statically in order to catch future library changes (unlikely but possible).

Another very important thing to consider however is the endianess of integral types, which varies among platforms. Most compilers for modern x86 desktop platforms use little endian for integral types, so I'd prefer this for your binary file format; but if the platform uses big endian you need to convert it (reverse the byte order).

like image 100
leemes Avatar answered Sep 30 '22 00:09

leemes