Jump to content
  • Advertisement
Sign in to follow this  
KulSeran

Endian. When do you care?

This topic is 4381 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Really this comes down to: when do you actually care about the endian of something? I understand the difference of big and little endian, and that it affects what you save out to a file. If a system is big endian, and I need to read in from a file saved in little endian, what changes? If I save an int(32bit) then I should be concernerned. What about a float(32bit) or a char array(4*8bit)? ---- More background, if I have a Read function can I make it deal with endianness without making: Read_uint16_LE2BE Read_uint16_BE2LE ..ect and without having Read ( data*, size, bool_endian_sensitive );

Share this post


Link to post
Share on other sites
Advertisement
Guest Anonymous Poster
int, yes. float, probably not. char array - not likely.

Share this post


Link to post
Share on other sites
I only care about endian when working with networks.
Since I am only working on little endian platforms I don t care about it in conjunction with binary files.
If you have to port your code to a big endian platform once, you add some compilation flags and add some conversion functions in your io implementation for binary data (htonl,....)

Share this post


Link to post
Share on other sites
It mostly matters when saving to a file that you want to be able to load on a different platform or when sending data over a network. It matters for any data type larger than 1 byte - int, float, long, double, bool (on some platforms), etc.

Share this post


Link to post
Share on other sites
Its the "atomic" types, that are greater than 1-byte in length, that matter..

So if I write on my PC


struct MyStruct
{
char name[32];
int a;
short b;
float c;
};
.
.
MyStruct data;
.
.
fwrite(&data, sizeof(a), 1, myFile);




Then when I read from my Mac, Xbox360, PS3, etc. I data.name will be ok, but I must swap a, b, and c.




fread(&data, sizeof(MyStruct), 1, myFile);
MYSWAPMACRO_32(&data.a);
MYSWAPMACRO_16(&data.b);
MYSWAPMACRO_32(&data.c);



Share this post


Link to post
Share on other sites
Thanks.
So, for just about anything that is not 8bit I would need to have support to swap the bytes around.
But since the char arrays are unaffected by endian, I can't just make a system that says:

read ( void *data, size_t size )
{
size_t bytes_read = fread ( file, size,1, data );
if ( bytes_read == 8 ) FixEndian64 ( data );
if ( bytes_read == 4 ) FixEndian32 ( data );
if ( bytes_read == 2 ) FixEndian16 ( data );
}



I would actually have to leave the swapping to the next higher level, where the datatype is known?

Share this post


Link to post
Share on other sites
Yes you have to know what data it is your reading to swap it correctly... So you could have your own ReadShort, ReadInt, etc. functions that do the appropriate swapping. But you could not just assume from the size of the read command (a read of 4 bytes could be of structure of two shorts or a single int etc..).

Edit... You could also rely on polymorphism, which could make you life a little easier...

e.g.


class MyReader
{
bool Read(int *pVal) { ReadSwapped32(pVal,sizeof(int)); )
bool Read(short *pVal) { ReadSwapped16(pVal,sizeof(short)); )
bool Read(char *pData, size_t n);// No swapping
.
.
}

reader.Read(myInt);
reader.Read(myShort);
reader.Read(myStr,32);



Share this post


Link to post
Share on other sites
Well, thanks griffin,
I'm mimiking the fstream.read and fread functionality, and so have no connection to the data,
but at a higher level I will need endian correctness, so I will probably come up with a polymorphic endian utility class that can be used by the subsystems that need it.

Share this post


Link to post
Share on other sites
you should also be aware that some casting that works on little-endian doesnt work at all on big endian-


typedef unsigned char byte;
int i = 255;
byte c = *((byte*)&i);
cout << c;


This will output 255 on a little endian system, and 0 on a big endian system.

If you need to do stuff like this, use a reinterpret_cast instaed of the crappy C-style cast I've used here.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by mattnewport
It mostly matters when saving to a file that you want to be able to load on a different platform or when sending data over a network. It matters for any data type larger than 1 byte - int, float, long, double, bool (on some platforms), etc.


Surely not float? Isn't it the same on all platforms with IEEE floating point?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!