3

i've searched for macro's to determine endianess on a machine and didn't found any standard proprocessor macros for this, but a lot of solutions doing that on runtime. why should i detect endianess at runtime?

if i do somthing like that:

#ifdef LITTLE_ENDIAN
  inline int swap(int& x) {
    // do swap anyhow
    return swapped;
  }
#elif BIG_ENDIAN
  inline int& swap(int& x) { return x; }
#else
  #error "some blabla"
#endif

int main() {
  int x = 0x1234;
  int y = swap(x);

  return 0;
}

the compiler will generate only one function.

but if i do it like (see predef.endian):

enum {
  ENDIAN_UNKNOWN,
  ENDIAN_BIG,
  ENDIAN_LITTLE,
  ENDIAN_BIG_WORD,   /* Middle-endian, Honeywell 316 style */
  ENDIAN_LITTLE_WORD /* Middle-endian, PDP-11 style */
};

int endianness(void)
{
  uint8_t buffer[4];

  buffer[0] = 0x00;
  buffer[1] = 0x01;
  buffer[2] = 0x02;
  buffer[3] = 0x03;

  switch (*((uint32_t *)buffer)) {
  case 0x00010203: return ENDIAN_BIG;
  case 0x03020100: return ENDIAN_LITTLE;
  case 0x02030001: return ENDIAN_BIG_WORD;
  case 0x01000302: return ENDIAN_LITTLE_WORD;
  default:         return ENDIAN_UNKNOWN;
}


int swap(int& x) {
  switch(endianess()) {
    case ENDIAN_BIG:
      return x;
    break;
    case LITTLE_ENDIAN:
      // do swap
      return swapped;
    break;
    default:
      // error blabla
  }
  // do swap anyhow
}

the compiler generates code for the detection.

i don't get it, why should i do this?

if i have code, compiled for a little-endian machine, the whole code is generated for little endian, and if i try to run such code on a big-endian machine (on a bi-endian machine like arm wiki:bi-endian) the whole code is compiled for a little-endian machine. so all other declarations of e.g. int are also le.

// compiled on little endian
uint32_t 0x1234;  // 0x1234 constant literal
// should result 34120000 on BE
user1810087
  • 5,146
  • 1
  • 41
  • 76

3 Answers3

6

There are actually systems where SOFTWARE can set whether the system is (currently running in) little or big endian mode. Most systems only support switching that under special circumstances, and not (fortunately for system programmers and such) switching back and forth arbitrarily. But it would be conceivable to support that an executable file defines whether that particular executable runs in LE or BE mode. In that case, you can't rely on picking out what OS and processor model it is...

On the other hand, if the hardware only EVER supports one endianness (e.g. x86 in its different forms), then I don't see a need to check at runtime. You know it's little endian, and that's it. It is wasteful (in terms of performance and code-size) to have the system contain code to check which endianness it is, and carry around conversion methods to convert from big endian to little endian.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • 1
    +1 [PowerPC](http://en.wikipedia.org/wiki/PowerPC#Endian_modes) is one such architecture. –  Apr 19 '13 at 17:54
  • I know that at least some ARM and MIPS as well as the now rather defunct 29K processor range can be configured for "set endian to this". Although it takes some careful planning to get it right, or you'll return to somewhere completely in the weeds, and changing it by accident because your code accidentially takes some random bits into a control register, I'm sure will make for VERY interesting debugging. – Mats Petersson Apr 19 '13 at 17:57
3

Robust endian detection at compile time isn't necessarily possible. There are platforms where endianess can change even between runs of the same binary.

http://gcc.gnu.org/ml/gcc-help/2007-07/msg00343.html

bames53
  • 86,085
  • 15
  • 179
  • 244
2

I think the only benefit of detecting endianness in runtime is that you don't have to mess around with macros. As you have noticed yourself, there is no standard macro saying what is the endiannes of the machine you are compiling your code on, so you must define something yourself and pass it to the compiler, or define it conditionally depending on other flags indicating architecture/operating system, something like:

#ifdef _this_system_
#define LITTLE_ENDIAN
#endif
#ifdef _that_system_
#define BIG_ENDIAN
#endif

but repeated many times, for every possible architecture, which is messy and error prone. It is easier and safer to check it in runtime. I know, it seems silly, but it is really more practical.

piokuc
  • 25,594
  • 11
  • 72
  • 102
  • 1
    When working on a cross-platform project, it's quite likely a buildsystem generator (AutoTools, CMake, SCons, ...) will be employed. This could also be used to detect the endianness (e.g. by building and running a small program) and pass the appropriate define to the compiler. – Angew is no longer proud of SO Apr 19 '13 at 17:01
  • Absolutely, I'm sure cmake and similar systems can provide a robust compile time solution, so if you use such a system, you can go for it. – piokuc Apr 19 '13 at 17:05
  • 1
    @Angew Be careful if you want to allow cross-compiling. – Klemens Baum Jul 26 '13 at 23:43