# Newbie SDL\_endian question

**URL:** <https://discourse.libsdl.org/t/newbie-sdl-endian-question/7244>\
**Category:** SDL Development\
**Created:** [August 13, 2002, 8:58pm UTC](https://discourse.libsdl.org/t/newbie-sdl-endian-question/7244 "2002-08-13T20:58:01Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![James\_Tittle\_II](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/j/9dc877/32.png) [@James\_Tittle\_II](https://discourse.libsdl.org/u/James_Tittle_II)\
**Post date:** [August 13, 2002, 8:58pm UTC](https://discourse.libsdl.org/t/newbie-sdl-endian-question/7244/1 "2002-08-13T20:58:01Z")

</div>

hiya,

…I’m undertaking my first fight with porting a game from x86 to ppc  
(OS X), and want a little reassurance that I’m doing the right thing  
with the byte swapping…

I didn’t find any info in the installed SDL docs, but saw this page  
([http://www.libsdl.org/intro/usingendian.html](http://www.libsdl.org/intro/usingendian.html)), which showed how to  
swap a 16 byte value…my confusion comes with how to correctly swap  
struct’s that are read in as a chunk, like in the following:

typedef struct VP\_FILE\_HEADER {  
char id[4];  
int version;  
int index\_offset;  
int num\_files;  
} VP\_FILE\_HEADER;

VP\_FILE\_HEADER VP\_header;

Assert( sizeof(VP\_header) == 16 );  
fread(&VP\_header, 1, sizeof(VP\_header), fp);

…as it is right now, the VP\_header.id comes out fine, but the rest  
come out kinda whacked…should I use a function to replace the  
fread() (along the lines of the “intro” example), or should this be  
done as a set of macros?

slowly outta th’gate,  
jamie

---

<div class="post-metadata">

**Author:** ![Adam\_Gates](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/a/da6949/32.png) [@Adam\_Gates](https://discourse.libsdl.org/u/Adam_Gates)\
**Post date:** [August 13, 2002, 9:26pm UTC](https://discourse.libsdl.org/t/newbie-sdl-endian-question/7244/2 "2002-08-13T21:26:01Z")

</div>

NEVER read in structs as a chunk!  
As well as endian issues  
you also have to deal with packing issues  
as well type size issues.

Write functions to read/write all of the inbuilt types which also  
perform byte swapping for you.  
Then write a read/write function for each structs which call other  
functions to read/write each member.

As a debugging/verification aid you can also read/write the size and type.  
Also use typedefs/defines for int sizes ie int8, int16, int32.

tigital wrote:\> hiya,

> …I’m undertaking my first fight with porting a game from x86 to ppc  
> (OS X), and want a little reassurance that I’m doing the right thing  
> with the byte swapping…
> 
> I didn’t find any info in the installed SDL docs, but saw this page  
> ([http://www.libsdl.org/intro/usingendian.html](http://www.libsdl.org/intro/usingendian.html)), which showed how to swap  
> a 16 byte value…my confusion comes with how to correctly swap struct’s  
> that are read in as a chunk, like in the following:
> 
> typedef struct VP\_FILE\_HEADER {  
> char id[4];  
> int version;  
> int index\_offset;  
> int num\_files;  
> } VP\_FILE\_HEADER;
> 
> VP\_FILE\_HEADER VP\_header;
> 
> Assert( sizeof(VP\_header) == 16 );  
> fread(&VP\_header, 1, sizeof(VP\_header), fp);
> 
> …as it is right now, the VP\_header.id comes out fine, but the rest  
> come out kinda whacked…should I use a function to replace the fread()  
> (along the lines of the “intro” example), or should this be done as a  
> set of macros?
> 
> slowly outta th’gate,  
> jamie

---

<div class="post-metadata">

**Author:** ![Christopher\_Subich](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/c/b38774/32.png) [@Christopher\_Subich](https://discourse.libsdl.org/u/Christopher_Subich)\
**Post date:** [August 13, 2002, 9:29pm UTC](https://discourse.libsdl.org/t/newbie-sdl-endian-question/7244/3 "2002-08-13T21:29:00Z")

</div>

At 11:57 PM 8/13/02 -0400, you wrote:

> hiya,
> 
> …I’m undertaking my first fight with porting a game from x86 to ppc (OS  
> X), and want a little reassurance that I’m doing the right thing with the  
> byte swapping…
> 
> I didn’t find any info in the installed SDL docs, but saw this page  
> ([http://www.libsdl.org/intro/usingendian.html](http://www.libsdl.org/intro/usingendian.html)), which showed how to swap a  
> 16 byte value…my confusion comes with how to correctly swap struct’s  
> that are read in as a chunk, like in the following:

In a struct (or any other ordered data structure), the order of the  
elements is preserved, but the order of the bytes in short, int, long, and  
long long (at least) are dependant on your system’s endianness. In your  
case, you want to convert the ints that you read to big-endian values [or  
write them that way when you save the file].–  
“It startled him even more when just after he was awarded the Galactic  
Institute’s Prize for Extreme Cleverness he got lynched by a rampaging mob  
of respectable physicists who had finally realized that the one thing they  
really couldn’t stand was a smart-ass.”  
– Hitchhiker’s Guide to the Galaxy

---

<div class="post-metadata">

**Author:** ![Christopher\_Subich](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/c/b38774/32.png) [@Christopher\_Subich](https://discourse.libsdl.org/u/Christopher_Subich)\
**Post date:** [August 13, 2002, 9:47pm UTC](https://discourse.libsdl.org/t/newbie-sdl-endian-question/7244/4 "2002-08-13T21:47:00Z")

</div>

At 02:12 PM 8/14/02 +1000, you wrote:

> NEVER read in structs as a chunk!  
> As well as endian issues  
> you also have to deal with packing issues  
> as well type size issues.

I’ve dealt with some of this in a little bit of network code – I’m not  
sure if “NEVER” is the best guideline.

Use caution, yes – the issues are quite valid. Only use component types  
of defined size, definitely.

Packing is possible, though, if you’re absolutely sure to use all of your  
compiler’s packing options for that section of code. #pragma pack(1)  
becomes extremely useful when you’re trying to create a 15-byte network packet.–  
“It startled him even more when just after he was awarded the Galactic  
Institute’s Prize for Extreme Cleverness he got lynched by a rampaging mob  
of respectable physicists who had finally realized that the one thing they  
really couldn’t stand was a smart-ass.”  
– Hitchhiker’s Guide to the Galaxy

---

<div class="post-metadata">

**Author:** ![Adam\_Gates](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/a/da6949/32.png) [@Adam\_Gates](https://discourse.libsdl.org/u/Adam_Gates)\
**Post date:** [August 13, 2002, 10:06pm UTC](https://discourse.libsdl.org/t/newbie-sdl-endian-question/7244/5 "2002-08-13T22:06:01Z")

</div>

I recommed NEVER not to imply its not possible but that it will save  
time in the long run  
especially if you are not the only who will use the code.

Christopher Subich wrote:\> At 02:12 PM 8/14/02 +1000, you wrote:

> > NEVER read in structs as a chunk!  
> > As well as endian issues  
> > you also have to deal with packing issues  
> > as well type size issues.
> 
> I’ve dealt with some of this in a little bit of network code – I’m not  
> sure if “NEVER” is the best guideline.
> 
> Use caution, yes – the issues are quite valid. Only use component  
> types of defined size, definitely.
> 
> Packing is possible, though, if you’re absolutely sure to use all of  
> your compiler’s packing options for that section of code. #pragma  
> pack(1) becomes extremely useful when you’re trying to create a 15-byte  
> network packet.
> 
> –  
> “It startled him even more when just after he was awarded the Galactic  
> Institute’s Prize for Extreme Cleverness he got lynched by a rampaging  
> mob of respectable physicists who had finally realized that the one  
> thing they really couldn’t stand was a smart-ass.”  
> – Hitchhiker’s Guide to the Galaxy

---

<div class="post-metadata">

**Author:** ![James\_Tittle\_II](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/j/9dc877/32.png) [@James\_Tittle\_II](https://discourse.libsdl.org/u/James_Tittle_II)\
**Post date:** [August 13, 2002, 10:27pm UTC](https://discourse.libsdl.org/t/newbie-sdl-endian-question/7244/6 "2002-08-13T22:27:00Z")

</div>

> I recommed NEVER not to imply its not possible but that it will save  
> time in the long run  
> especially if you are not the only who will use the code.
> 
> Christopher Subich wrote:
> 
> > At 02:12 PM 8/14/02 +1000, you wrote:
> > 
> > > NEVER read in structs as a chunk!  
> > > As well as endian issues  
> > > you also have to deal with packing issues  
> > > as well type size issues.
> > 
> > I’ve dealt with some of this in a little bit of network code – I’m  
> > not sure if “NEVER” is the best guideline.
> > 
> > Use caution, yes – the issues are quite valid. Only use component  
> > types of defined size, definitely.
> > 
> > Packing is possible, though, if you’re absolutely sure to use all  
> > of your compiler’s packing options for that section of code.  
> > #pragma pack(1) becomes extremely useful when you’re trying to  
> > create a 15-byte network packet.

well, I just tried:

```
     if ( SDL_BYTEORDER == SDL_BIG_ENDIAN ) {
         VP_header.version = SDL_Swap32( VP_header.version);
         VP_header.index_offset = SDL_Swap32( VP_header.index_offset);
         VP_header.num_files = SDL_Swap32( VP_header.num_files);
     }

```

…which seems to give correct results!

tanx for the push in the right direction!

jamie

---

<div class="post-metadata">

**Author:** ![icculus](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/icculus/32/81_2.png) [@icculus](https://discourse.libsdl.org/u/icculus)\
**Post date:** [August 14, 2002, 3:26am UTC](https://discourse.libsdl.org/t/newbie-sdl-endian-question/7244/7 "2002-08-14T03:26:01Z")

</div>

> I’ve dealt with some of this in a little bit of network code – I’m not  
> sure if “NEVER” is the best guideline.

Never _is_ the best guideline.

Either send as individual units, or pack it manually, or whatnot.

“#pragma pack()” isn’t a universal solution, nor does it help with byte  
swapping.

It is EASY to serialize objects when you first write disk/network code,  
and it is a severe motherf\*\*\*er to do it later. The bugs are subtle, hard  
to find, and viscious.

You have been warned. Do it right the first time.

–ryan.

---

<div class="post-metadata">

**Author:** ![icculus](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/icculus/32/81_2.png) [@icculus](https://discourse.libsdl.org/u/icculus)\
**Post date:** [August 14, 2002, 3:29am UTC](https://discourse.libsdl.org/t/newbie-sdl-endian-question/7244/8 "2002-08-14T03:29:00Z")

</div>

> ```
> if ( SDL_BYTEORDER == SDL_BIG_ENDIAN ) {
> VP_header.version = SDL_Swap32( VP_header.version);
> VP_header.index_offset = SDL_Swap32( VP_header.index_offset);
> VP_header.num_files = SDL_Swap32( VP_header.num_files);
> }
> 
> ```
> 
> …which seems to give correct results!

Even better:

VP\_header.version = SDL\_SwapLE32(VP\_header.version);  
VP\_header.index\_offset = SDL\_SwapLE32(VP\_header.index\_offset);  
VP\_header.num\_files = SDL\_SwapLE32(VP\_header.num\_files);

Which says "take this 32bit littleendian (intel) data and convert it to  
the native byte order.

On x86, this dithers down to:

VP\_header.version = VP\_header.version;  
VP\_header.index\_offset = VP\_header.index\_offset;  
VP\_header.num\_files = VP\_header.num\_files;

If you’re lucky, your compiler might optimize that out altogether. On  
PowerPC, it’ll be a byte-swapping macro.

–ryan.
