Re: Help: How to determine big/little endian?

nr@cs.purdue.edu (Norman Ramsey)
Fri, 25 Aug 1995 22:14:24 GMT

          From comp.compilers

Related articles
[4 earlier articles]
Re: Help: How to determine big/little endian? mw@ipx2.rz.uni-mannheim.de (1995-08-22)
Re: Help: How to determine big/little endian? tonyk@cybercom.net (1995-08-22)
Re: Help: How to determine big/little endian? paysan@informatik.tu-muenchen.de (1995-08-21)
Re: Help: How to determine big/little endian? tim@franck.Princeton.EDU (1995-08-25)
Re: Help: How to determine big/little endian? meissner@cygnus.com (Michael Meissner) (1995-08-25)
Re: Help: How to determine big/little endian? cwf@research.att.com (Chris Fraser) (1995-08-25)
Re: Help: How to determine big/little endian? nr@cs.purdue.edu (1995-08-25)
Re: Help: How to determine big/little endian? doug@netcom.com (1995-08-26)
Re: Help: How to determine big/little endian? meissner@cygnus.com (Michael Meissner) (1995-09-01)
Re: Help: How to determine big/little endian? mab@wdl.loral.com (1995-09-01)
Re: Help: How to determine big/little endian? erik@kroete2.freinet.de (1995-09-03)
Re: Help: How to determine big/little endian? daniels@cse.ogi.edu (1995-09-13)
Re: Help: How to determine big/little endian? wdavis@dw3f.ess.harris.com (1995-09-26)
| List of all articles for this month |

Newsgroups: comp.arch,comp.compilers
From: nr@cs.purdue.edu (Norman Ramsey)
Keywords: C, architecture
Organization: Department of Computer Science, Purdue University
References: <4074ig$nh7@masala.cc.uh.edu> 95-08-182
Date: Fri, 25 Aug 1995 22:14:24 GMT

Bernd Paysan <paysan@informatik.tu-muenchen.de> wrote:
>> So, how about it, GNU and ANSI ? Let's see __BIGEND__
>> and __LITTLEEND__ incorporated into the standards.
>> Thanks.
>
>I would support your request. Especially I found out that it is quite a
>problem not having anything that you can rely on. E.g. when we (that's
>Anton Ertl and me) started writing gforth, we used a macro BIGENDIAN
>that was only defined, when the machine was b.e.. No we compiled under
>Linux, and (surprise!) the program didn't work correct. Why? Linux'
>include files define BIGENDIAN 0 when the machine is l.e., and BIGENDIAN 1
>if it is b.e. :-(. Now we use WORDS_BIGENDIAN (that's what autoconf uses)
>and hope, that this is unique...


I've been trying to resist putting my oar in, but I can't stop myself!
Perhaps the moderator will shut me up if necessary.


If you need to know your host's byte order, it's easy to test things at
run time. At the cost of a pointer indirection per some calls, you
can set suitable function pointers at program startup and forget about
byte order forever after. You shouldn't be horsing around with
preprocessor symbols unless you have measurements showing that a
run-time detection strategy is too expensive.


But you don't need to know it for this:


>In code where you desire to have a specified byte order, thus read/writing
>binary file formats accross platforms, network code...


Moderator says:


>[For reading and writing binary files, I've had great success using shifts,
>masks, getc(), and putc() to assemble and disassemble multi-byte data on
>the way in or out. I agree that there are some places where knowing the
>byte order makes life easier. -John]


Hear, hear. Here are a couple of code fragments from the New Jersey
Machine-Code Toolkit library, where we have to be able to emit values
of a specified width and endianness, no matter what the host byte
order. (Calls to this emission code typically get generated from
high-level machine descriptions.)


    <<emit [[n]] bytes of [[val]] at [[p]] (little-endian)>>=
    switch (n) {
        #define BYTE(N) case N+1: p[N] = val >> 8*N; /* fall through */
        BYTE(7) BYTE(6) BYTE(5) BYTE(4) BYTE(3) BYTE(2) BYTE(1) BYTE(0)
        #undef BYTE
        case 0: /* do nothing */
            break;
        default: assert(("unsigned long bigger than 8 bytes", 0));
    }


    <<emit [[n]] bytes of [[val]] at [[p]] (big-endian)>>=
    switch (n) {
        #define S(POS, N) (p[POS] = val >> 8*N)
        case 0: break;
        case 1: S(0,0); break;
        case 2: S(0,1); S(1,0); break;
        case 3: S(0,2); S(1,1); S(2,0); break;
        case 4: S(0,3); S(1,2); S(2,1); S(3,0); break;
        case 5: S(0,4); S(1,3); S(2,2); S(3,1); S(4,0); break;
        case 6: S(0,5); S(1,4); S(2,3); S(3,2); S(4,1); S(5,0); break;
        case 7: S(0,6); S(1,5); S(2,4); S(3,3); S(4,2); S(5,1); S(6,0); break;
        case 8: S(0,7); S(1,6); S(2,5); S(3,4); S(4,3); S(5,2); S(6,1); S(7,0); break;
        default: assert(("unsigned long bigger than 8 bytes", 0));
    }


I'll note in passing that if you promise that (a) host and target have
the same byte order, and (b) all alignment restrictions are met, we
have a library routine that does the moral equivalent of
((unsigned *)p)++ = n
(yes, I know that's not legal C).


Similar code works for reading stuff in a known byte order.


I love disk and network formats that have fixed byte orders.
Down with the X protocol!


--
Norman Ramsey
nr@cs.purdue.edu
--


Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.