C++ Reading bytes Problem
I have this issue, I don't know if is expected, here is the thing:
I'm trying to load bytes from a file to an structure like this:
struct
{
char
char
char
char
unsigned int
}
but the problem is when the unsigned int is filled, it seems like in the reading stream the b开发者_Go百科ytes are swapped, e.x. if the file contains 0x45080000, the unsigned int will have 0x84500000, which is wrong.
This can be "solved" if i change the unsigned int for a BYTE[4], but is not what I want. Here is the code that I use to read from the file:
fopen_s( &mFile, "myFile.ext", "rb" );
if( mFile == NULL ) print( " **** E R R O R ! **** " );
else
{
if( fread( &myStruct, sizeof( MY_Struct ), 1, myFile) != 1)
{
print( " **** E R R O R ! **** " );
return 0;
}
}
Is this an expected behavior or what am I doing wrong?
Regards
As you've discovered, portable serialization can be a pain. Instead of writing and reading the structure, you need to serialize each attribute individually in a normalized format (network byte order is common). Then when you deserialize the bytes come back correctly.
Either serialize/unserialize each field independently (standards conforming) or...
use a platform specific option:
#pragma pack(push,1)
struct foo {
// ...
};
#pragma pack(pop)
This aligns all variables in foo to 1 byte alignment, so it wont work for a boolean.
If you intend to be cross-platform you'll have to test the hell out of it for problems of endianess and pragma support.
Just to add a bit of icing to the cake!
You must handle 32 vs. 64 bit issues also.
A very good include file is stdint.h (C99). It defines types with specific size so you get less problems when switching the word width.
you probably need to take into account big/little endian. try s.th. like this:
#define BIG_ENDIAN
//#define LITTLE_ENDIAN
...
#ifdef BIG_ENDIAN
inline void writeMem32(uint8* buf, uint32 val)
{
buf[0] = static_cast<uint8>(val >> 24);
buf[1] = static_cast<uint8>(val >> 16);
buf[2] = static_cast<uint8>(val >> 8);
buf[3] = static_cast<uint8>(val >> 0);
}
inline uint32 readMem32(const uint8* buf)
{
return ( ((*(buf+0)) << 24) | ((*(buf+1)) << 16) | ((*(buf+2)) << 8) | (*(buf+3)) );
}
#endif // BIG_ENDIAN
if you are on little endian the byte order is of course different :)
精彩评论