user79758
user79758

Reputation:

How can I detect endianness on a system where all primitive integer sizes are the same?

(This question came out of explaining the details of CHAR_BIT, sizeof, and endianness to someone yesterday. It's entirely hypothetical.)

Let's say I'm on a platform where CHAR_BIT is 32, so sizeof(char) == sizeof(short) == sizeof(int) == sizeof(long). I believe this is still a standards-conformant environment.

The usual way to detect endianness at runtime (because there is no reliable way to do it at compile time) is to make a union { int i, char c[sizeof(int)] } x; x.i = 1 and see whether x.c[0] or x.c[sizeof(int)-1] got set.

But that doesn't work on this platform, as I end up with a char[1].

Is there a way to detect whether such a platform is big-endian or little-endian, at runtime? Obviously it doesn't matter inside this hypothetical system, but one can imagine it is writing to a file, or some kind of memory-mapped area, which another machine reads and reconstructs it according to its (saner) memory model.

Upvotes: 1

Views: 2019

Answers (8)

Sparr
Sparr

Reputation: 7712

You could shift the variable in question and see which end the 1 shifts off of.

Upvotes: 0

please delete me
please delete me

Reputation:

htonl should work:

if(htonl(1)==1) {
   /* network order (big-endian) */
} else {
   /* little-endian */
}

(I can't see any reason not to implement htonl and friends in the usual fashion, even for this annoying hypothetical system -- though I'm not sure how much help they would turn out to be in practice.)

Upvotes: 0

Martin B
Martin B

Reputation: 24130

I suppose the question boils down to: Is endianness even a meaningful concept on this platform, i.e. does it have a detectable influence on the behaviour of a program?

If it doesn't, then endianness (i.e. the order in which the individual bytes making up a 32-bit quantity are stored in memory) is merely an implementation detail which you can't detect, but which needn't concern you either.

If endianness does have a detectable influence on the behaviour of a certain aspect of the language... well, then construct a test based on that behaviour. Here are some examples:

  • How does the addressing system on the platform work? If you increment an address by one, to how many bits does that correspond? If the answer is eight bits and the system allows you to read from addresses that aren't a multiple of four, then you can move a pointer forward by a single byte (via a detour to intptr_t) and test for endianness that way. (Yes, this is implementation-defined behaviour, but so is using a union to test for endianness as well as the whole concept of endianness in general.) If, however, the smallest addressable unit of memory is 32 bytes, then you can't test for endianness this way.

  • Does the platform have a 64-bit data type (a long long)? Then you can create a union of a long long and two ints and construct your endianness-test based on that.

Upvotes: 2

bestsss
bestsss

Reputation: 12056

The question doesn't offer enough info but w/ what it does offer I'd say: not possible.

Upvotes: 0

wilx
wilx

Reputation: 18228

If your code relies on knowing whether architecture is BE or LE then your code should have a safety and not compile for unknown platform. Some #if ! defined(ARCH_IS_LE) && ! defined(ARCH_IS_BE) \ #error unknown architecture should do.

Upvotes: -1

Christoph
Christoph

Reputation: 169533

The concept of endianness only makes sense for scalar types represented by multiple bytes. By definition, a char is single-byte, so any integer type having the same size as char has no endianness.

Also keep in mind that endianness can be different for different types: For example, the PDP-11 is a little-endian 16-bit architecture, and 32-bit integers are built from two 16-bit little-endian values, ending up mixed endian.

Upvotes: 4

SoapBox
SoapBox

Reputation: 20609

Structure bitfields should still work properly on any platform, even this one:

union {
   int i;
   struct {
       int b1 : 8;
       int b2 : 8;
       int b3 : 8;
       int b4 : 8;
   } s;
} u;

u.i = 1;
if (u.s.b1 != 0)
   ....

Upvotes: 0

Al Kepp
Al Kepp

Reputation: 5980

Hypothetically, in an environment where all data types are of the same size, there is no endianess.

I can see three possibilities for you:

  • If the limitation is only given by C compiler and technically the platform has some smaller data types, you can use assembler to detect endianess.

  • If the platform supports double data type, you can use it to detect endianess, because it is always 64 bits wide.

  • Also you can write data to file, as you suggested, and then read back. Simply write two chars (file in binary mode), move file pointer to position 1 and read back a char.

Upvotes: 4

Related Questions