# Calculating Endian type at runtime (and adapting to it)

• 06-26-2005
JoshR
Calculating Endian type at runtime (and adapting to it)
Well I've researched some endian calculating techniques and can't find a way to achieve what I want. I basically want to have a certain union type name be associated with the union that corresponds with the correct endian.

This is what I have so far and I know it doesnt work, I'm not very good at preprocessor directives because I really dont ever use them, but I've tried everything so I just left it in the code. Here is the code, it calculates the correct endian (I think) but just doesn't define the right type.

Code:

```#include <iostream> using namespace std; ///////////////////////////////////////////////// typedef unsigned int CHAR32; //----------------------------------------------- // Breaks up 32 bits into blocks of 8 bits // BITBLOCKSB for Big-Endian // BITBLOCKSL for Little-Endian //----------------------------------------------- struct BITBLOCKSB {   unsigned char    one;   unsigned char    two;   unsigned char  three;   unsigned char  four; }; struct BITBLOCKSL {   unsigned char  four;   unsigned char  three;   unsigned char    two;   unsigned char    one; }; //----------------------------------------------- // Allows access to the bit blocks of a value // BITUNIONB for Big-Endian // BITUNIONL for Little-Endian //----------------------------------------------- typedef union {   CHAR32      value;   BITBLOCKSB  bits; } BITUNIONB; typedef union {   CHAR32      value;   BITBLOCKSL  bits; } BITUNIONL; //----------------------------------------------- // Current PC endian type //----------------------------------------------- bool ENDIAN() {   short int bit = 1;   char* byte = (char*) &bit;   return (byte[0] ? true : false); } //----------------------------------------------- const bool BIGENDIAN = ENDIAN(); //-----------------------------------------------  #if (BIGENDIAN)   #define BITUNION BITUNIONB #else   #define BITUNION BITUNIONL #endif ///////////////////////////////////////////////// int main() {   BITUNION bitUnion;   bitUnion.value = 254;   cout << (int)bitUnion.bits.one << " " << (int)bitUnion.bits.two << " "       << (int)bitUnion.bits.three << " " << (int)bitUnion.bits.four;         cout << endl << "Big Endian? " << (BIGENDIAN ? " Yes" : " No") << endl;   cin.get();   return 0; }```
• 06-26-2005
grumpy
Code:

```int BigEndianSystem() {     unsigned char SwapTest[2] = { 1, 0 };       switch (*(unsigned short *)SwapTest)     {         case 0U :  return 0;  // little endian         case 1U : return 1;  // big endian         default: return -1;  // something else (middle endian!) - extremely rare AFAIK     } }```
• 06-26-2005
JoshR
I already have a function that works, but I don't know how to correctly assign the type name BITUNION to the correct endian union (its the stuff in red thats troubling me)
• 06-26-2005
Salem
> const bool BIGENDIAN = ENDIAN();
> #if (BIGENDIAN)
These are two unrelated things, despite having the same name.

The only way to manipulate the #if is by specifying either
- in the source code #define BIGENDIAN 0 or #define BIGENDIAN 1
- on the command line -DBIGENDIAN=0 or #define BIGENDIAN 1

At which point, your assignment becomes illegal code as the preprocessor substitues
const bool BIGENDIAN = ENDIAN();
to be say for example
const bool 1 = ENDIAN();

Since you have no #define or -D options, when the pre-processor reaches
#if (BIGENDIAN)
it generates
#define BIGENDIAN 0
for you, then evaluates the #if expression.
• 06-26-2005
JoshR
Ahhh just what I was not looking to hear, ya so preprocessor is really pre compile and everything, it isnt dynamic during runtime etc... do you have any suggestions of how I might approach this otherwise?
• 06-26-2005
Salem
> do you have any suggestions of how I might approach this otherwise?
Create a function which has an interface which doesn't care about endian-ess, and which resolves the actual endian-ess in use (using your code to detect endian-ess) to control what actually happens.

This can be quite a performance drag if you're doing lots of bit fiddling, so most people just go with the -DENDIAN type command line option when compiling.

If you want, you can put a specific test at the start of main() say which checks the -D option with the apparent endian-ess returned by your function and complain if there's a mis-match.

Run-time determination of endian-ess is problematic at best
http://en.wikipedia.org/wiki/Endianness
• 06-26-2005
grumpy
Oh OK. You want the name of different fields to change depending on endianness.

The following will do a run time check, but that check only ever needs to be done once;

Code:

```///////////////////////////////////////////////// typedef unsigned int CHAR32; typedef union {   CHAR32      value;   unsigned char bits[4]; } BITUNION; int one; int two; int three; int four; //----------------------------------------------- // Current PC endian type //----------------------------------------------- bool ENDIAN() {   short int bit = 1;   char* byte = (char*) &bit;   return (byte[0] ? true : false); } bool BIGENDIAN; int main() {   if (BIGENDIAN = ENDIAN())  // yes, single = in here is deliberate   {         one = 0;         two = 1;         three = 2;         four = 3;   }   else   {         one = 3;         two = 2;         three = 1;         four = 0;   }   BITUNION bitUnion;   bitUnion.value = 254;   cout << (int)bitUnion.bits[one] << " " << (int)bitUnion.bits[two] << " "       << (int)bitUnion.bits[three] << " " << (int)bitUnion.bits[four];         cout << endl << "Big Endian? " << (BIGENDIAN ? " Yes" : " No") << endl;   cin.get();   return 0; }```
• 06-26-2005
JoshR
Heres what I came up with, based on grumpy's code, and salems smartness.

Code:

```#include <iostream> using namespace std; ///////////////////////////////////////////////// typedef unsigned int CHAR32; //----------------------------------------------- // Current PC endian type //----------------------------------------------- bool ENDIAN() {   short int bit = 1;   char* byte = (char*) &bit;   return (byte[0] ? false : true); } //----------------------------------------------- const bool BIGENDIAN = ENDIAN(); //----------------------------------------------- // Breaks up 32 bits into blocks of 8 bits //----------------------------------------------- struct BITBLOCKS {   unsigned char    one;   unsigned char    two;   unsigned char  three;   unsigned char  four; }; //----------------------------------------------- // Allows access to the bit blocks // Operator to help assign depending on endian //----------------------------------------------- union BITUNION {   CHAR32        value;   BITBLOCKS      bits;   void operator= (CHAR32 val); }; void BITUNION::operator= (CHAR32 val) {   value = val;   if (BIGENDIAN)   {     bits.four  = val & 255; val >>= 8;     bits.three = val & 255; val >>= 8;     bits.two  = val & 255; val >>= 8;     bits.one  = val & 255;   } } //-----------------------------------------------  ///////////////////////////////////////////////// int main() {   BITUNION bitUnion;   bitUnion = 6254;   cout << (int)bitUnion.bits.one << " " << (int)bitUnion.bits.two << " "       << (int)bitUnion.bits.three << " " << (int)bitUnion.bits.four;         cout << endl << "Big Endian? " << (BIGENDIAN ? " Yes" : " No") << endl;   cin.get();   return 0; }```
• 06-26-2005
JoshR
Will someone with a little endian system test mine? lol I know thats an insane question to ask because nobody really thinks about their endian type, but if someone gets big endian == yes could you post the order of the numbers? thanks, I just want to see if it works corretly like it should.
• 06-26-2005
Salem
Your endian test is inverted - it should be returning false for x86 systems, not true.
• 06-26-2005
JoshR
k thanks