I generally typedef my own types which are an exact bitwidth. <stdint.h> has a bunch of these types, but apparently that's not standard (although I could've swore it was)
1 2 3 4 5
|
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;
// repeat for signed counterparts
|
Alternatively you can use <stdint.h>'s uint8_t, uint16_t, etc.
Sizes of these can be confirmed with a sizeof() at program startup:
1 2 3
|
if(sizeof(u8) != 1) throw "u8 wrong size";
if(sizeof(u16) != 2) throw "u16 wrong size";
if(sizeof(u32) != 4) throw "u32 wrong size";
|
Then, rather than writing an 'int' to a file, you write a fixed-size variable to a file instead. This will ensure it gets read properly on any platform because the appropriate size can be typedef'd to fit.
Another thing to watch for it endianness. Reading/writing multi-byte variables are subject to system endianness. ie: writing a 32-bit value 0x01020304 to a file on a little endian machine, then reading it back on a big endian machine will give you 0x04030201.
To solve this I wrote some template functions which break up the value and read/write it one byte at a time. These are for my personal file wrapper class, but you can get the jist of them and apply them to whatever file IO method you're using:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
template <typename T>
bool PutInt(T v)
{
size_t i;
u8 by;
for(i = 0; i < sizeof(T); ++i)
{
by = (u8)(v >> (i*8));
if(Write(&by,sizeof(u8)) <= 0)
return false;
}
return true;
}
template <typename T>
T GetInt(bool* isok = 0)
{
size_t i;
T ret = 0;
u8 by;
for(i = 0; i < sizeof(T); ++i)
{
if(Read(&by,sizeof(u8)) <= 0)
{
if(isok) *isok = false;
return ret;
}
ret |= (T)by << (i*8);
}
if(isok) *isok = true;
return ret;
}
///////////////////////////////////////
// to use
myfile.PutInt<u32>(5); // write 5 to file in endian-safe manner
u32 something = myfile.GetInt<u32>(); // read from file
|
I also have GetInts() and PutInts() which take an array... they just loop and call the above functions.
Reading/writing floating points in a safe way is another can of worms and is something I haven't really thought about yet because I haven't had need to do it yet.