Little Endian to Big Endian

Luminary
Posts: 5,143
Joined: 2002.04
Post: #16
I don't care where you test for endianness -- whether you have two completely separate file-loading functions, or whether you have two different implementations of a readInt32 function, or whether you have a big ugly mess with a bunch of

Code:
#if defined(__BIG_ENDIAN__)
swap32(data);
#endif

scattered everywhere, or whether you write a function like this:

Code:
static inline uint32_t uint32_little_to_host(uint32_t n)
{
#if defined(__BIG_ENDIAN__)
    return ((n & 0x000000ff) << 24) |
           ((n & 0x0000ff00) << 8)  |
           ((n & 0x00ff0000) >> 8)  |
           ((n & 0xff000000) >> 24);
#else
    return n;
#endif
}

or whatever strikes your fancy; just use a compile-time check, not a run-time one!
Quote this message in a reply
Member
Posts: 161
Joined: 2005.07
Post: #17
akb825 Wrote:64 bit computers are the same as 32 bit as far as endianness is concerned.
This is directed towards the original author, but keep in mind that on 64-bit computers, sizeof(float/int/bool/etc.) are 8 bytes instead of 4 (64 bits = 8 bytes). This means that when you want to read in a float or an int or something, make sure you just type a 4 instead of using sizeof or it might be unreliable.

fread(&num, 4, 1, file) <--- something like that I think
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #18
imikedaman Wrote:This is directed towards the original author, but keep in mind that on 64-bit computers, sizeof(float/int/bool/etc.) are 8 bytes instead of 4 (64 bits = 8 bytes). This means that when you want to read in a float or an int or something, make sure you just type a 4 instead of using sizeof or it might be unreliable.

fread(&num, 4, 1, file) <--- something like that I think
You are mistaken. The only difference (at least on the Mac) is that longs are 64 bits instead of 32. bool, int, and float are all still 32 bit. (and double is still 64 bit, and long double is still undefined, but I believe it is 128 bits on my G5)
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #19
For reference:

Mac, 32-bit PPC:
sizeof(char) == 1
sizeof(short) == 2
sizeof(int) == sizeof(long) == sizeof(void*) == sizeof(size_t) == sizeof(float) == sizeof(bool) == 4
sizeof(long long) == sizeof(double) == 8

Mac, 64-bit PPC:
sizeof(char) == 1
sizeof(short) == 2
sizeof(int) == sizeof(float) == sizeof(bool) == 4
sizeof(long) == sizeof(void*) == sizeof(size_t) == sizeof(long long) == sizeof(double) == 8

Mac, 32-bit i386:
sizeof(char) == sizeof(bool) == 1
sizeof(short) == 2
sizeof(int) == sizeof(long) == sizeof(void*) == sizeof(size_t) == sizeof(float) == 4
sizeof(long long) == sizeof(double) == 8

Mac, 64-bit i386:
Find out in early August Wink

Note that on Win64, long is still 32 bits, unlike Mac and Linux.

Note that sizeof(long double) on Mac OS X depends both on architecture and on compiler version. I think that sizeof(long double) == 8 (GCC 3.x/PPC), 16 (GCC 4.x/PPC) and 16 (GCC 4.x/x86), but on x86 the math is done on the x87 unit, which means it's done at only 80 bits of precision, and with a few other caveats. I can't verify those numbers now though (not on a Mac).

If you *ever* care about the size of an integer type, you should use the types in <stdint.h>:
int32_t is a 32-bit integer
uint64_t is an unsigned 64-bit integer
etc.
Quote this message in a reply
Member
Posts: 161
Joined: 2005.07
Post: #20
Really? If that's true, it gives me one more reason to stop listening to my ass hole computer science teachers. Thanks for the enlightenment.
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #21
Either that computer science teacher has no idea what he's talking about, or he's using some obscure compiler to have those sizes.
Quote this message in a reply
Member
Posts: 161
Joined: 2005.07
Post: #22
akb825 Wrote:Either that computer science teacher has no idea what he's talking about, or he's using some obscure compiler to have those sizes.
He says Mac OS Ex. I rest my case. Wacko
Quote this message in a reply
Jones
Unregistered
 
Post: #23
What's wrong with run time checks? Please, tell me! Blink
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #24
No one seems to have bothered to explain themselves. Here are some reasons:
  • Since they never change at runtime, checking at runtime wastes CPU cycles.
  • Since they should never change at runtime, you'd have a potential source of obscure program failure if your endianness variable somehow gets a different value written to it.
  • Runtime checks are unconventional. (Pretty weak reason, but worth mentioning.)
For reference, here's how I handle it:
Code:
#define swapInt32(int32) ((((int32) >> 24) & 0x000000FF) | \
                          (((int32) >> 8)  & 0x0000FF00) | \
                          (((int32) << 8)  & 0x00FF0000) | \
                          (((int32) << 24) & 0xFF000000))

#if defined(__BIG_ENDIAN__)

#define swapInt32Big(int32) (int32)
#define swapInt32Little(int32) swapInt32(int32)

#elif defined(__LITTLE_ENDIAN__)

#define swapInt32Big(int32) swapInt32(int32)
#define swapInt32Little(int32) (int32)

#else
#error Endianness unknown; cannot proceed
#endif
When I'm reading or writing a big-endian value, I call swapInt32Big. When I'm reading or writing a little-endian value, I call swapInt32Little. When/if I need other types than int32, I can easily add similar macros to support them.
Quote this message in a reply
Oldtimer
Posts: 834
Joined: 2002.09
Post: #25
I just go with htonl() and ntohl() and be done with it.
Quote this message in a reply
Jones
Unregistered
 
Post: #26
ThemsAllTook Wrote:No one seems to have bothered to explain themselves. Here are some reasons:
  • Since they never change at runtime, checking at runtime wastes CPU cycles.
  • Since they should never change at runtime, you'd have a potential source of obscure program failure if your endianness variable somehow gets a different value written to it.
  • Runtime checks are unconventional. (Pretty weak reason, but worth mentioning.)
For reference, here's how I handle it:
Code:
#define swapInt32(int32) ((((int32) >> 24) & 0x000000FF) | \
                          (((int32) >> 8)  & 0x0000FF00) | \
                          (((int32) << 8)  & 0x00FF0000) | \
                          (((int32) << 24) & 0xFF000000))

#if defined(__BIG_ENDIAN__)

#define swapInt32Big(int32) (int32)
#define swapInt32Little(int32) swapInt32(int32)

#elif defined(__LITTLE_ENDIAN__)

#define swapInt32Big(int32) swapInt32(int32)
#define swapInt32Little(int32) (int32)

#else
#error Endianness unknown; cannot proceed
#endif
When I'm reading or writing a big-endian value, I call swapInt32Big. When I'm reading or writing a little-endian value, I call swapInt32Little. When/if I need other types than int32, I can easily add similar macros to support them.

Thats what I meant when I said to OneSadCookie, "declare the same function, but in one if it's with a conversion, and the other it isn't". Admittedly, It was not very clear. I guess I can understand the lost CPU cycles (I hate coding something while knowing all along it's performance is less than it could be.).

Very well, I shall fix it. Smile

Just Checking, doing this is ok, oui?

Code:
#if defined(__BIG_ENDIAN__)
swapINT(num1);
        swapINT(num2);
#endif

Supposing, num1 and num2 had just been loaded from a file.
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #27
Jones Wrote:Just Checking, doing this is ok, oui?

Code:
#if defined(__BIG_ENDIAN__)
swapINT(num1);
        swapINT(num2);
#endif

Supposing, num1 and num2 had just been loaded from a file.
Sure, that'll work. The only thing is that it clutters your file I/O code a bit. If you use a macro or a function which behaves differently depending on the endianness (as in my example), you only have to have the preprocessor checks in that one place.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #28
Fenris Wrote:I just go with htonl() and ntohl() and be done with it.

That's of no use if you're trying to read a little-endian file...
Quote this message in a reply
Oldtimer
Posts: 834
Joined: 2002.09
Post: #29
Quote:That's of no use if you're trying to read a little-endian file...
Oops. I've been following a similar thread over at GameDev.net, forgot that his file format was LE. Sorry 'bout that.
Quote this message in a reply
Jones
Unregistered
 
Post: #30
Is there any difference between swapping an unsigned int and a normal int? They're both 4 bytes.

I'm guessing no.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Endian-ness ia3n_g 11 4,128 Sep 20, 2006 11:47 PM
Last Post: OneSadCookie
  Even *MORE* endian issues Jones 22 6,522 Aug 3, 2006 06:40 PM
Last Post: Jones