# Safe endian macro

## Recommended Posts

Hi,

Here what I'm curently using :

#if defined( __m68k__ ) || defined( mc68000 ) || defined( _M_M68K ) || ( defined( __MIPS__ ) && defined( __MISPEB__ ) ) || \
defined( __ppc__ ) || defined( __POWERPC__ ) || defined( _M_PPC ) || defined( __sparc__ ) || defined( __hppa__ )
#ifndef ENDIAN_BIG
#define ENDIAN_BIG
#endif // ENDIAN_BIG
#else
#ifndef ENDIAN_LITTLE
#define ENDIAN_LITTLE
#endif // ENDIAN_LITTLE
#endif // ENDIAN

Is it safe enough or more check is needed ?

Thanks

##### Share on other sites

This is what I use. You might be able to extract extra checks from this. Note the disclaimer.

http://files.sandmines.org/sml_endian.hpp

##### Share on other sites

An M68k? Sparc? The freaking HPPA?? What on earth are you coding that requires this level of flexibility? (If it's a generic header for 'everything', stop and do something else that is grounded in reality.)

Even in the multi-system *nix world that tends to develop that type of laundry-list of devices, they are typically added individually as each new system adds support.

I suppose if the original code was starting with a fork of the already cross-platform Frozen Bubbles or something similar, that might make some sense.

##### Share on other sites

I changed to that, gives a code lines multiplied by 3 for the platform/architecture/endian detection but surely a lot more safe.

##### Share on other sites

This, of course, is going to break if (and when) a new architecture comes out that you haven't already accounted for.

How about just storing a number in a short or an int, then checking the value of it's bytes and converting if needed at runtime?  That's similar to the method used by e.g the Quake engine games and it will work irrespective of what future architectures might appear (https://github.com/id-Software/Quake/blob/master/WinQuake/common.c#L1127):

byte swaptest[2] = {1, 0};

if (*(short *) swaptest == 1)
bigendien = false;
else bigendien = true;


##### Share on other sites

I work a lot with embedded, and in particular files and memory dumps from embedded systems. In my experience, it doesn't matter that much if you are running on one or the other, what matters is if you are working with files/data from the other one. Almost all files/dumps/structures/whatever have some magic number header where we just do something like

if(val == 0xAABBCCDD)
{
}
else if(val == 0xDDCCBBAA)
{
}
else

{

throw new InvalidDataException();

}

I suppose it could matter if you try to write a file with a defined byte order though.

Also, many processors have runtime switchable endianess, including most ARMs if I'm not mistaken. :)

Edited by DvDmanDT

##### Share on other sites

This, of course, is going to break if (and when) a new architecture comes out that you haven't already accounted for.

How about just storing a number in a short or an int, then checking the value of it's bytes and converting if needed at runtime?  That's similar to the method used by e.g the Quake engine games and it will work irrespective of what future architectures might appear (https://github.com/id-Software/Quake/blob/master/WinQuake/common.c#L1127):

byte swaptest[2] = {1, 0};

if (*(short *) swaptest == 1)
bigendien = false;
else bigendien = true;


Yeah, I vote for this as well. I just run the following at startup and leave it at that:

bool Endian::isSystemLittleEndian()
{
short number = 0x1;
char *numPtr = (char*)&number;
return (numPtr[0] == 1);
}


##### Share on other sites
The downside with all the above suggested runtime techniques is just that - they're runtime.

In my experience there are only three places where endianess matters - when I'm loading a file off of disk with an unknown endian format, when I'm dealing with network packets, and when I'm writing out data to be used on another platform.

The first one should be minimized - and eliminated if possible - by always making sure a platform loads native assets and save games and whatnot. Now, during development you'll want to support it so you can transfer savegames and assets between platforms - but your release build probably doesn't need to handle it. This is usually handled with having a magic number at the start of your file header and, if it doesn't match on read, endian swapping it and checking again. It doesn't need to know what endianess it is - only if it's different then the asset.

The second one can be done at compile time since you know what endianess your network packets will have, and the endianess of your machine - so no runtime choices have to be made.

The third is arguably the only one that needs to know what its endianess is - but this is also usually a tool thing, and tools can afford to be slower then a game.

So in short - you don't need to know at runtime in a game. You might need to know at runtime in a tool. Basically - you want to avoid a bunch of "should I swap?" checks every time you read in a small amount of data from your files as that will hurt loading times. Edited by SmkViper

## Create an account

Register a new account

• ### Forum Statistics

• Total Topics
628337
• Total Posts
2982164

• 9
• 24
• 9
• 9
• 13