Little Endian to Big Endian
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
scattered everywhere, or whether you write a function like this:
or whatever strikes your fancy; just use a compile-time check, not a run-time one!
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!
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
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.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)
fread(&num, 4, 1, file) <--- something like that I think
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
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.
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

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.
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.
Either that computer science teacher has no idea what he's talking about, or he's using some obscure compiler to have those sizes.
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.

No one seems to have bothered to explain themselves. Here are some reasons:
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.
- 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.)
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
ThemsAllTook Wrote:No one seems to have bothered to explain themselves. Here are some reasons:For reference, here's how I handle it:
- 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.)
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.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
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.

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.
Jones Wrote:Just Checking, doing this is ok, oui?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.
Code:
#if defined(__BIG_ENDIAN__)
swapINT(num1);
swapINT(num2);
#endif
Supposing, num1 and num2 had just been loaded from a file.
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: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.
Possibly Related Threads...
Thread: | Author | Replies: | Views: | Last Post | |
Endian-ness | ia3n_g | 11 | 6,665 |
Sep 20, 2006 11:47 PM Last Post: OneSadCookie |
|
Even *MORE* endian issues | Jones | 22 | 11,702 |
Aug 3, 2006 06:40 PM Last Post: Jones |