Big Endian/Little Endian 
Author Message
 Big Endian/Little Endian

It's been a while seen I've read Gulliver's Travels.  From a quick
look at the posted code, I'm assuming that we're talking about  most
and least  significant bits and how to convert.  Which end is up?


Quote:


>>Is there an elegant way to convert big endian to little endian and vice
>>versa in ??

>Not really.

>You might look at swab(), if your system has it (the unix mention implies
>that it might...).

>Also, Dan Bernstein came up with an arguably elegant, but not portable,
>hack:
>    unsigned long swap = 0x01020304;
>    unsigned char *swapper = (unsigned char *) &swap;
>    int_type new;
>    unsigned char *newc = (unsigned char *) &new;
>    int i;
>    for (i = 0; i < sizeof(new); ++i) {
>            newc[i] = old[swapper[i]];
>    }

>Clever, huh?  In practice, it turns out to be slower than shifts and
>masks on some systems, but the relative portability is neat.

>>I have a 3rd party supplied database that contains longs and floats in
>>little endian and need to convert them on the fly to big endian running
>>under Solaris using gnu C.  Any help would be appreciated.

>This will probably not be sufficient; you may also be seeing much more
>general problems with the floating point formats.

>You may want to find out exactly what processors are on each end, so
>you can get docs on likely floating point formats.  "solaris" could be
>80x86 or SPARC, easily, and "little-endian" tells us next to nothing.

>Not that we want to know; your answer is really "get docs on the
>data formats and chips, and go from there".  There's nothing elegant.

>-s
>--

>Copyright 1997.  All rights reserved.  This was not written by my cat.
>C/Unix wizard - send mail for help! -- <URL: http://www.*-*-*.com/ ~seebs>
><URL: http://www.*-*-*.com/ ; - More Net, Less Spam!

--



Mon, 01 May 2000 03:00:00 GMT  
 Big Endian/Little Endian

Quote:

> Is there an elegant way to convert big endian to little endian and vice
> versa in ??
> I have a 3rd party supplied database that contains longs and floats in
> little endian and need to convert them on the fly to big endian running
> under Solaris using gnu C.  Any help would be appreciated.

Here's some code fragments that may help.   They use the shift operator
and depend on the the data you're swapping on being memory aligned
so that you can treat them as longs...  the idea being that accessing
a long is faster than accessing a byte (on a 32-bit CPU).

One warning.   You must use unsigned types when you do shifting.
There are two kinds of right shifts (down shifts).   Those that
shift in zero's from the left ("zero extend" or "logical shifts")
and those that shift in the sign bit ("sign extend", or "arithmetic
shifts"):

   zero-extend    1000 0000 >> 1   becomes   0100 0000
   sign-extend    1000 0000 >> 1   becomes   1100 0000

If you use an unsigned type, you are guarenteed to get a zero-extend
shift, but if you use a signed type, the implementation may be
system dependent.

/* Swapping a long (or float) */
main(){

   unsigned long x;

   x=0x01020304;
   x=(x>>24) | (x>>8)&0xff00 | (x<<8)&0xff0000 | (x<<24) ;
   printf("0x%08x\n", x);

Quote:
}

/* Swapping a double */
main(){

     double a;
     unsigned long *x;

     *x     = (unsigned long *)(&a);
     *(x++) = (*x>>24) | (*x>>8)&0xff00 | (*x<<8)&0xff0000 | (*x<<24) ;
     *x     = (*x>>24) | (*x>>8)&0xff00 | (*x<<8)&0xff0000 | (*x<<24) ;

Quote:
}

--
***********************************************************************
Computer Programming is the Art of the Possible
Gary Lucas                                              Sonalysts, Inc.

Work: (860)442-4355                                 Waterford CT 06385
***********************************************************************
--



Mon, 01 May 2000 03:00:00 GMT  
 Big Endian/Little Endian

Ollie. You are likely to find that "endianness" is not the only issue
confronting you. The relative sizes of the mantissa and exponent
sections changes from architecture to architecture as well.

You will need documentation containing the bit arrangements of floats
and doubles for each platform and have to do some bit twiddling. I've
done this myself and will say that while it's not difficult it is
tedious.

Good Luck
Robert Egan

Quote:

> Is there an elegant way to convert big endian to little endian and
> vice versa in ??

> I have a 3rd party supplied database that contains longs and floats in
> little endian and need to convert them on the fly to big endian
> running under Solaris using gnu C.  Any help would be appreciated.

> Thanks - Ollie

--
To reply by mail, set nospam ==> regan
--



Mon, 01 May 2000 03:00:00 GMT  
 Big Endian/Little Endian

Quote:

>union
>{
> long original;
> short New[2];
>} endian; /*original and the array of two shorts occupy the same memory*/
>endian a;
>a.original = somevalue;
>new[0]^=new[1]; new[1]^=new[0];new[0]^=new[1];
>printf("%ld", a.original);

I presume this was not scored as 100% correct...
"Big|little endian" needs more precise definition,
but usually it applies to the octet string,
not to some arbitrary-but-no-less-than-16-bit string
(which is what "short" gets you).
Also, the XOR swap trick looks cute,
but it is usually slower than the obvious way.

--



Mon, 01 May 2000 03:00:00 GMT  
 Big Endian/Little Endian

[snip]

Quote:
>Wow! I just participated in the ACM Programming Contest (Regional for New
>York) and that was the first problem given.

>This is basically the way we implemented it.

>union
>{
>    long original;
>    short New[2];
>} endian; /*original and the array of two shorts occupy the same memory*/

>endian a;
>a.original = somevalue;
>new[0]^=new[1]; new[1]^=new[0];new[0]^=new[1];
>printf("%ld", a.original);

     The problem with the xor method is that if the values being
swapped are the same, xoring will zero one of the values.

     The solution is also very implementation defined.

  1) What if long and short are the same size or more generally, what
if long is not twice short's size?
  2) The code won't work if short is more than one character (which is
usually considering that short must be at least 16 bits and most char
are eight), but will simply swap the two halves. i.e. 1234 should be
swapped to 4321 but will instead be munged to 3412.

Quote:
>and ditto for floats.

Sincerely,

Gene Wirchenko

C Pronunciation Guide:
     y=x++;     "wye equals ex plus plus semicolon"
     x=x++;     "ex equals ex doublecross semicolon"
--



Mon, 01 May 2000 03:00:00 GMT  
 Big Endian/Little Endian


Quote:
> >union
> >{
> > long original;
> > short New[2];
> >} endian; /*original and the array of two shorts occupy the same memory*/
> >endian a;
> >a.original = somevalue;
> >new[0]^=new[1]; new[1]^=new[0];new[0]^=new[1];
> >printf("%ld", a.original);
> I presume this was not scored as 100% correct...

I presume it was scored as 100% correct, as it was an ACM Regional.
The jury in such contests doesn't inspect the code. They test it
on their platform with a secret test set. The goal in these contests
is to produce correct results on the test sets.  Not to write
strictly confirming or portable code.  At least, that was the
situation when our team participated in these contests, including
the finals.

        Marcel
--  _   _
  _| |_|_|
 |_    |_     Marcel van Kervinck

--



Mon, 01 May 2000 03:00:00 GMT  
 Big Endian/Little Endian


Quote:
>> Is there an elegant way to convert big endian to little endian and
>> vice versa in ??

>> I have a 3rd party supplied database that contains longs and floats in
>> little endian and need to convert them on the fly to big endian
>> running under Solaris using gnu C.  Any help would be appreciated.

>> Thanks - Ollie

The XDR (eXternal Data Representation) libraries can provide a good solution for
platform independent storage/retrieval of simple data types (for the platforms
it exists on, nearly all Unix, ports for PC), but won't address reading your
database initially.

Jeremy Beal
Get my e-mail address at www.nvmedia.com/jbeal
(Tired of the damn spam)
--



Mon, 01 May 2000 03:00:00 GMT  
 Big Endian/Little Endian

Is there an elegant way to convert big endian to little endian and vice
versa in ??

I have a 3rd party supplied database that contains longs and floats in
little endian and need to convert them on the fly to big endian running
under Solaris using gnu C.  Any help would be appreciated.

Thanks - Ollie
--



Mon, 01 May 2000 03:00:00 GMT  
 Big Endian/Little Endian


Quote:

>Is there an elegant way to convert big endian to little endian and vice
>versa in ??

Not really.

You might look at swab(), if your system has it (the unix mention implies
that it might...).

Also, Dan Bernstein came up with an arguably elegant, but not portable,
hack:
        unsigned long swap = 0x01020304;
        unsigned char *swapper = (unsigned char *) &swap;
        int_type new;
        unsigned char *newc = (unsigned char *) &new;
        int i;
        for (i = 0; i < sizeof(new); ++i) {
                newc[i] = old[swapper[i]];
        }

Clever, huh?  In practice, it turns out to be slower than shifts and
masks on some systems, but the relative portability is neat.

Quote:
>I have a 3rd party supplied database that contains longs and floats in
>little endian and need to convert them on the fly to big endian running
>under Solaris using gnu C.  Any help would be appreciated.

This will probably not be sufficient; you may also be seeing much more
general problems with the floating point formats.

You may want to find out exactly what processors are on each end, so
you can get docs on likely floating point formats.  "solaris" could be
80x86 or SPARC, easily, and "little-endian" tells us next to nothing.

Not that we want to know; your answer is really "get docs on the
data formats and chips, and go from there".  There's nothing elegant.

-s
--

Copyright 1997.  All rights reserved.  This was not written by my cat.
C/Unix wizard - send mail for help! -- <URL:http://www.plethora.net/~seebs>
<URL:http://www.plethora.net/> - More Net, Less Spam!
--



Mon, 01 May 2000 03:00:00 GMT  
 Big Endian/Little Endian


Quote:
> Is there an elegant way to convert big endian to little endian and vice
> versa in ??

> I have a 3rd party supplied database that contains longs and floats in
> little endian and need to convert them on the fly to big endian running
> under Solaris using gnu C.  Any help would be appreciated.

> Thanks - Ollie
> --


Wow! I just participated in the ACM Programming Contest (Regional for New
York) and that was the first problem given.

This is basically the way we implemented it.

union
{
        long original;
        short New[2];

Quote:
} endian; /*original and the array of two shorts occupy the same memory*/

endian a;
a.original = somevalue;
new[0]^=new[1]; new[1]^=new[0];new[0]^=new[1];
printf("%ld", a.original);

and ditto for floats.

Josh Waxman
--



Mon, 01 May 2000 03:00:00 GMT  
 Big Endian/Little Endian

Quote:

> Is there an elegant way to convert big endian to little endian and vice
> versa in ??
> I have a 3rd party supplied database that contains longs and floats in
> little endian and need to convert them on the fly to big endian running
> under Solaris using gnu C.  Any help would be appreciated.
> Thanks - Ollie
> --


You might try something like the following....  IMPORTANT, always
use unsigned integer types when swapping bytes.   If you use
signed types, some implementations of C (like the old VAX VMS)
will extend the sign bit

   1000 0000 0000 0000  >> 1  becomes      1100 0000 0000 0000
                              rather than  0100 0000 0000 0000

Is been so long since I looked, I've forgotten what the ANSI-C standard
is now...   But I stick with unsigned just to avoid any problems.

main(){
   unsigned long x;
   x=0x01020304;
   x=(x>>24) | (x>>8)&0xff00 | (x<<8)&0xff0000 | (x<<24) ;
   printf("0x%08x\n", x);

Quote:
}

--
***********************************************************************
Computer Programming is the Art of the Possible
Gary Lucas                                              Sonalysts, Inc.

Work: (860)442-4355                                 Waterford CT 06385
***********************************************************************
--



Mon, 01 May 2000 03:00:00 GMT  
 Big Endian/Little Endian



Quote:

>> Is there an elegant way to convert big endian to little endian and vice
>> versa in ??

>> I have a 3rd party supplied database that contains longs and floats in
>> little endian and need to convert them on the fly to big endian running
>> under Solaris using gnu C.  Any help would be appreciated.

>> Thanks - Ollie
>> --

>Wow! I just participated in the ACM Programming Contest (Regional for New
>York) and that was the first problem given.

>This is basically the way we implemented it.

>union
>{
>        long original;
>        short New[2];
>} endian; /*original and the array of two shorts occupy the same memory*/

>endian a;
>a.original = somevalue;
>new[0]^=new[1]; new[1]^=new[0];new[0]^=new[1];
>printf("%ld", a.original);

There are a couple of errors in this. Changing between big and little endian
typically means reversal of data at the char/byte level not at the "short"
level. Accessing a value in a union which has been stored in a different
union member produces implementation-defined behaviour i.e. it isn't
guaranteed to behave how you want. Also you are assuming the relative
sizes of the member types. C doesn't guarantee anything about the relative
sizes of short and long.

--
-----------------------------------------


-----------------------------------------
--



Mon, 01 May 2000 03:00:00 GMT  
 Big Endian/Little Endian



Quote:


>>Is there an elegant way to convert big endian to little endian and vice
>>versa in ??

>Not really.

>You might look at swab(), if your system has it (the unix mention implies
>that it might...).

The XPG3 swab() function only swaps adjacent pairs of bytes so probably isn't
going to be much help here.

Quote:
>Also, Dan Bernstein came up with an arguably elegant, but not portable,
>hack:
>        unsigned long swap = 0x01020304;
>        unsigned char *swapper = (unsigned char *) &swap;
>        int_type new;
>        unsigned char *newc = (unsigned char *) &new;
>        int i;
>        for (i = 0; i < sizeof(new); ++i) {
>                newc[i] = old[swapper[i]];
>        }

old doesn't seem to be defined anywhere.

Quote:
>Clever, huh?  In practice, it turns out to be slower than shifts and
>masks on some systems, but the relative portability is neat.

The method is portable if the aim is to reverse the order of bytes in an
object.  The question is whether that is a portable definition of the
problem that needs to be solved...

Quote:
>>I have a 3rd party supplied database that contains longs and floats in
>>little endian and need to convert them on the fly to big endian running
>>under Solaris using gnu C.  Any help would be appreciated.

...or a portable solution may not be required at all.

Quote:
>This will probably not be sufficient; you may also be seeing much more
>general problems with the floating point formats.

Hopefully both platforms use IEEE 754 formats which should eliminate most
compatibility problems.

Quote:
>You may want to find out exactly what processors are on each end, so
>you can get docs on likely floating point formats.  "solaris" could be
>80x86 or SPARC, easily, and "little-endian" tells us next to nothing.

>Not that we want to know; your answer is really "get docs on the
>data formats and chips, and go from there".  There's nothing elegant.

I can't disagree with that! :-)

--
-----------------------------------------


-----------------------------------------
--



Mon, 01 May 2000 03:00:00 GMT  
 Big Endian/Little Endian

Quote:


> > Is there an elegant way to convert big endian to little endian
> > and vice versa in ??

<snippage>

> /* Swapping a double */
> main(){

>   double a;
>   unsigned long *x;

>   *x     = (unsigned long *)(&a);

    ^^
Are you sure this is correct?

Quote:
>   *(x++) = (*x>>24) | (*x>>8)&0xff00 | (*x<<8)&0xff0000 | (*x<<24) ;
>   *x     = (*x>>24) | (*x>>8)&0xff00 | (*x<<8)&0xff0000 | (*x<<24) ;
>}

This code seems to be a little bit processor specific to me,
remember a long might not be four bytes(!).

This will swap a long of any size:

void SwapLong(long *l)
{
  unsigned char tmp, *a, *b;

  a = (unsigned char*)l;
  b = a + sizeof(long);

  while (a < b) {
    tmp = *a;
    *a++ = *--b;
    *b = tmp;
  }

Quote:
}

Or you could use the method posted by Seebs which "straightens out"
a piece of data on any machine (without having to know the byte
order).

--
<\___/>      | THE LESSER-KNOWN PROGRAMMING LANGUAGES #8: LAIDBACK
/ O O \      | Considered to be a gentle and non-threatening language
\_____/ FTB. | since all error messages are in lower case.
--



Mon, 01 May 2000 03:00:00 GMT  
 Big Endian/Little Endian

Quote:

> Is there an elegant way to convert big endian to little endian and vice
> versa in ??

This may not fit your needs, but may be of use to others:

I use ntohl() and htonl() (Network to Host Long and vice-versa, part of
the BSD sockets package), as a portable way of converting from
whatever-host-endian into big-endian (TCP/IP network byte order is
big-endian).  

You can find the ntohl() family of functions on all Unixes, WinNT/95,
and VxWorks, to name a few...

--
\'/.\'/.\'/.\'/.\'/.\'/.\'/.\'/.\'/.\'/.\'/.\'/.\'/.\'/.\'/.\
/.\'/  Brian Silverman      Chesapeake Sciences Corp.   /.\'/

/.\'/.\'/.\'/.\'/.\'/.\'/.\'/.\'/.\'/.\'/.\'/.\'/.\'/.\'/.\'/
--



Mon, 01 May 2000 03:00:00 GMT  
 
 [ 33 post ]  Go to page: [1] [2] [3]

 Relevant Pages 

1. Big endian, little endian question.

2. Big Endian/Little Endian

3. Big Endian - Little Endian

4. Floats: Big-endian/Little-endian conversion

5. big endian, little endian

6. big-endian - little-endian help for floats

7. big-endian - little endian problem

8. Big Endian/Little Endian

9. Read double little endian on big endian machine

10. Big Endian->Little Endian for floats

11. big endian on SUN to little endian on Intel conversion

12. big-endian vs. little-endian

 

 
Powered by phpBB® Forum Software