I’m working on a file format that should be written and read in several different operating systems and computers. Some of those computers should be x86 machines, others x86-64. Some other processors may exist, but I’m not concerned about them yet.
This file format should contain several numbers that would be read like this:
struct LongAsChars{
char c1, c2, c3, c4;
};
long readLong(FILE* file){
int b1 = fgetc(file);
int b2 = fgetc(file);
int b3 = fgetc(file);
int b4 = fgetc(file);
if(b1<0||b2<0||b3<0||b4<0){
//throwError
}
LongAsChars lng;
lng.c1 = (char) b1;
lng.c2 = (char) b2;
lng.c3 = (char) b3;
lng.c4 = (char) b4;
long* value = (long*) &lng;
return *value;
}
and written as:
void writeLong(long x, FILE* f){
long* xptr = &x;
LongAsChars* lng = (LongAsChars*) xptr;
fputc(lng->c1, f);
fputc(lng->c2, f);
fputc(lng->c3, f);
fputc(lng->c4, f);
}
Although this seems to be working on my computer, I’m concerned that it may not in others or that the file format may end up being different across computers(32 bits vs 64 bits computers, for example).
Am I doing something wrong? How should I implement my code to use a constant number of bytes per number?
Should I just use fread(which would possibly make my code faster too) instead?
Use the types in
stdint.hto ensure you get the same number of bytes in and out.Then you’re just left with dealing with endianness issues, which you code probably doesn’t
really handle.
Serializing the long with an aliased char* leaves you with different byte orders in the written file for platforms with different endianess.
You should decompose the bytes something like so:
And recompose then using something like: