I would like to know, is there a way to retrieve the endianness
of the underlying platform programmatically from a C/POSIX program?
In particular is it possible to check for big endian, little endian,
or other endians?
In absense of a function call of macro definition that would serve
this purpose, is there a POSIX or otherwise common Unix shell command
which can be used to report the endianness of the underlying platform?
Thanks,
Neil
> I would like to know, is there a way to retrieve the endianness
> of the underlying platform programmatically from a C/POSIX program?
> In particular is it possible to check for big endian, little endian,
> or other endians?
#include <stdint.h>
int little_endian()
{
union {
uint32_t i;
uint8_t c[4];
} e;
e.i = 1;
return e.c[0];
}
For other than big or little endian more elaborate checks will be
required. Are there still any such machines around?
--
Måns Rullgård
m...@users.sf.net
> #include <stdint.h>
>
> int little_endian()
> {
> union {
> uint32_t i;
> uint8_t c[4];
> } e;
>
> e.i = 1;
> return e.c[0];
> }
>
> For other than big or little endian more elaborate checks will be
> required. Are there still any such machines around?
That is not too difficult.
enum {
ENDIAN_UNKNOWN,
ENDIAN_BIG,
ENDIAN_LITTLE,
ENDIAN_BIG_WORD, /* Middle-endian, PDP-11 style */
ENDIAN_LITTLE_WORD /* Middle-endian, Honeywell 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 0x01000301: return ENDIAN_LITTLE_WORD;
default: return ENDIAN_UNKNOWN;
}
Usually endianess is only needed when (de)marshalling binary data.
In such cases it is easier to write endian-agnostic (de)marshalling
functions such as the following. Please note that they assume that
the exchange format is big-endian (network byte-order). Furthermore,
these functions can easily be adapted to other integer types, simply
by changing the type at the "/* Type */" comments.)
#include <limits.h>
/* Type */ unsigned int
endian_native_unsigned_int(/* Type */ unsigned int net_number)
{
/* Type */ unsigned int result = 0;
int i;
for (i = 0; i < (int)sizeof(result); i++) {
result <<= CHAR_BIT;
result += (((unsigned char *)&net_number)[i] & UCHAR_MAX);
}
return result;
}
/* Type */ unsigned int
endian_net_unsigned_int(/* Type */ unsigned int native_number)
{
/* Type */ unsigned int result = 0;
int i;
for (i = (int)sizeof(result) - 1; i >= 0; i--) {
((unsigned char *)&result)[i] = native_number & UCHAR_MAX;
native_number >>= CHAR_BIT;
}
return result;
}