Reputation:
(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
Reputation: 7712
You could shift the variable in question and see which end the 1 shifts off of.
Upvotes: 0
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
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 int
s and construct your endianness-test based on that.
Upvotes: 2
Reputation: 12056
The question doesn't offer enough info but w/ what it does offer I'd say: not possible.
Upvotes: 0
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
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
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
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