Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

retrieving endianness programmatically

7 views
Skip to first unread message

Neil Zanella

unread,
Mar 29, 2003, 6:12:34 PM3/29/03
to

Hello,

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

Måns Rullgård

unread,
Mar 29, 2003, 7:30:37 PM3/29/03
to
Neil Zanella <nzan...@cs.mun.ca> writes:

> 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

Bjorn Reese

unread,
Mar 30, 2003, 7:16:06 AM3/30/03
to
Måns Rullgård wrote:

> #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;
}

0 new messages