Endian-ness

Member
Posts: 49
Joined: 2006.07
Post: #1
Alright, I'm finally taking the plunge and making a universal binary. All I really need to do is swap the bytes when loading the levels, since I'm not using any textures or anything.
Now, the way I read an int (or a float) from a file already is to call this function:

Code:
static Boolean Read(int &i)
{
       for(unsigned int j=0;j<sizeof(int);j++)
    {
        inChar=fgetc(infile);
        if (inChar==EOF)
            return false;
        *( ( (char *) &i)+j)=inChar;
    }
       return true;
}

First off, is it stupid to read the int as a succession of chars?
Secondly, it seems like if I just put in some test to see which architecture I'm on, I could just run the for loop the other way, and get the right result, without any speed hit for byte swapping. But Apple's docs recommend against using the ___BIG_ENDIAN___ macros, which I imagine are what I use to test which architecture I'm on. Is running the for loop backwards on Intel an advisable way of going? (And is doing it this way advisable on either platform?)
Quote this message in a reply
Member
Posts: 161
Joined: 2005.07
Post: #2
ia3n_g Wrote:First off, is it stupid to read the int as a succession of chars?
Yep, considering there's a built-in way to read them:
Code:
int blah;
fread(&blah, 4, 1, infile);
It's also not advisable to use sizeof(int) when reading ints from a file, since no matter how large ints are on the architecture, the file only has four bytes being allocated for the int anyway.
Quote this message in a reply
Member
Posts: 49
Joined: 2006.07
Post: #3
So should I use fread and then one of the CF swap functions?
Quote this message in a reply
Member
Posts: 161
Joined: 2005.07
Post: #4
Yeah, that's fine.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #5
ia3n_g Wrote:But Apple's docs recommend against using the ___BIG_ENDIAN___ macros)

They do? Where, if I may ask?

You should always used fixed-size types when doing I/O. There are a standard set in <stdint.h> called uint32_t and so forth.
Quote this message in a reply
Member
Posts: 49
Joined: 2006.07
Post: #6
What are OSReadLittleInt16 and OSWriteLittleInt16? I know I'd need the 32 bit version if they are relevant. I've seen them mentioned but I can't find documentation on them. Are they for file I/O?
Quote this message in a reply
Member
Posts: 49
Joined: 2006.07
Post: #7
OneSadCookie Wrote:They do? Where, if I may ask?

In "Guidelines for Swapping Bytes" it says:
"Use the __BIG_ENDIAN__ and __LITTLE_ENDIAN__ macros only if you must."
http://developer.apple.com/documentation...3-CJBBHCFG


Granted I may be placing more emphasis on that than I'm meant to.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #8
Weird Smile

The OS.. byte-swapping routines are in <libkern/OSByteOrder.h> ( /usr/include/libkern/OSByteOrder.h ). They were added in 10.4.
Quote this message in a reply
Member
Posts: 49
Joined: 2006.07
Post: #9
I'm running 10.4, but I don't have the libkern folder.
And how do they differ from the CF byte swapping routines?
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #10
Whoops, should have read "include", not "lib" (I've edited the post).

They differ from the CF ones in that they're different from the CF ones Rasp
Quote this message in a reply
Moderator
Posts: 3,571
Joined: 2003.06
Post: #11
ia3n_g Wrote:In "Guidelines for Swapping Bytes" it says:
"Use the __BIG_ENDIAN__ and __LITTLE_ENDIAN__ macros only if you must."
http://developer.apple.com/documentation...3-CJBBHCFG


Granted I may be placing more emphasis on that than I'm meant to.
That is indeed weird, so I decided to read a little further into it...

Here's another quote from that same document:
Quote:The C preprocessor has several predefined macros whose purpose is to indicate the type of system
and machine in use. If your code uses system-specific predefined macros, evaluate whether you really
need to use them. In most cases applications need to know the capabilities available on a computer
and not the specific system or machine on which the application is running. For example, if your
application needs to know whether it is running on a little-endian or big-endian microprocessor, you
should use the __BIG_ENDIAN__ or __LITTLE_ENDIAN__ macros or the Core Foundation function
CFByteOrderGetCurrent. Do not use the __i386__ and __ppc__ macros for this purpose.

Given this and all the other stuff I've read in code sample comments, and just common sense, I would say that the quote:

"Use the __BIG_ENDIAN__ and __LITTLE_ENDIAN__ macros only if you must."

Needs to be put in the context of the sentence following it as well:

"Do not use macros that check for a specific processor type, such as __i386__ and __ppc__."

Furthermore, I would guess that the first sentence was actually meant to be written:

"Use the __BIG_ENDIAN__ and __LITTLE_ENDIAN__ macros only, if you must."

(notice my addition of the comma) Heck, I think the `if you must.' part could have been left out in the first place. The bottom line is that you should use __BIG_ENDIAN__ and __LITTLE_ENDIAN__ when it makes sense to do so. Smile
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #12
I think their point is that eg. OSSwapHostToBigInt32 compiles to nothing on a PowerPC machine anyway, so you shouldn't write

Code:
#if defined(__LITTLE_ENDIAN__)
x = OSSwapHostToBigInt32(x);
#endif

because it's exactly the same as

Code:
x = OSSwapHostToBigInt32(x);

In terms of what the compiler generates.

I do think it's rather misleading, though!
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Confused with array-ness Tobs_ 4 3,178 Aug 12, 2007 05:37 PM
Last Post: JeroMiya
  Even *MORE* endian issues Jones 22 6,463 Aug 3, 2006 06:40 PM
Last Post: Jones
  Little Endian to Big Endian Jones 42 13,947 Jul 20, 2006 12:07 PM
Last Post: Jones