Thread overview
bit twiddling (endianness)
Jan 08, 2007
Lutger
Jan 08, 2007
Daniel Keep
Jan 08, 2007
torhu
Jan 08, 2007
Daniel Keep
Jan 08, 2007
Lutger
Jan 11, 2007
Stewart Gordon
Jan 11, 2007
Lutger
January 08, 2007
Hi, I need to convert a uint to 4 ubytes in big endian order for which I have written the function below. The thing is, I'm not 100% sure it is correct for Big Endian systems, would somebody be so kind as to inform me if this will work?

void concatUint(inout ubyte[] bytestream, uint num)
{
    bytestream.length = bytestream.length + 4;
    static if (std.system.endian == Endian.LittleEndian)
    {
        bytestream[$-4] = num >> 24;
        bytestream[$-3] = num >> 16;
        bytestream[$-2] = num >> 8;
        bytestream[$-1] = num;
    }
    else // big endian
    {
        bytestream[$-4] = num;
        bytestream[$-3] = num >> 8;
        bytestream[$-2] = num >> 16;
        bytestream[$-1] = num >> 24;
    }
}
January 08, 2007
Lutger wrote:
> Hi, I need to convert a uint to 4 ubytes in big endian order for which I have written the function below. The thing is, I'm not 100% sure it is correct for Big Endian systems, would somebody be so kind as to inform me if this will work?
> 
> void concatUint(inout ubyte[] bytestream, uint num)
> {
>     bytestream.length = bytestream.length + 4;
>     static if (std.system.endian == Endian.LittleEndian)
>     {
>         bytestream[$-4] = num >> 24;
>         bytestream[$-3] = num >> 16;
>         bytestream[$-2] = num >> 8;
>         bytestream[$-1] = num;
>     }
>     else // big endian
>     {
>         bytestream[$-4] = num;
>         bytestream[$-3] = num >> 8;
>         bytestream[$-2] = num >> 16;
>         bytestream[$-1] = num >> 24;
>     }
> }

Taking, as an example, 0x0A0B0C0D: for little endian it should be stored as 0x0D0C0B0A, and for big endian it should be 0x0A0B0C0D.

0x0A0B0C0D >> 24 == 0x0A, so I *think* you've got them backwards.

http://en.wikipedia.org/wiki/Little_Endian#Big-endian

	-- Daniel
January 08, 2007
Lutger wrote:
> Hi, I need to convert a uint to 4 ubytes in big endian order for which I have written the function below. The thing is, I'm not 100% sure it is correct for Big Endian systems, would somebody be so kind as to inform me if this will work?
> 
> void concatUint(inout ubyte[] bytestream, uint num)
> {
>      bytestream.length = bytestream.length + 4;
>      static if (std.system.endian == Endian.LittleEndian)
>      {
>          bytestream[$-4] = num >> 24;
>          bytestream[$-3] = num >> 16;
>          bytestream[$-2] = num >> 8;
>          bytestream[$-1] = num;
>      }
>      else // big endian
>      {
>          bytestream[$-4] = num;
>          bytestream[$-3] = num >> 8;
>          bytestream[$-2] = num >> 16;
>          bytestream[$-1] = num >> 24;
>      }
> }


Since you haven't done any weird casting, the compiler (or is it cpu?) knows that num is an uint.  So the bit shifting will behave like num is big endian, no matter the endianness of the system.

In other words, your code for little endian systems is correct for big endian too.  But your big endian code swaps the byte order, resulting in little endian order in bytestream.
January 08, 2007
torhu wrote:
> Lutger wrote:
> 
>> Hi, I need to convert a uint to 4 ubytes in big endian order for which I have written the function below. The thing is, I'm not 100% sure it is correct for Big Endian systems, would somebody be so kind as to inform me if this will work?
>>
>> void concatUint(inout ubyte[] bytestream, uint num)
>> {
>>      bytestream.length = bytestream.length + 4;
>>      static if (std.system.endian == Endian.LittleEndian)
>>      {
>>          bytestream[$-4] = num >> 24;
>>          bytestream[$-3] = num >> 16;
>>          bytestream[$-2] = num >> 8;
>>          bytestream[$-1] = num;
>>      }
>>      else // big endian
>>      {
>>          bytestream[$-4] = num;
>>          bytestream[$-3] = num >> 8;
>>          bytestream[$-2] = num >> 16;
>>          bytestream[$-1] = num >> 24;
>>      }
>> }
> 
> 
> 
> Since you haven't done any weird casting, the compiler (or is it cpu?) knows that num is an uint.  So the bit shifting will behave like num is big endian, no matter the endianness of the system.
> 
> In other words, your code for little endian systems is correct for big endian too.  But your big endian code swaps the byte order, resulting in little endian order in bytestream.

Yup: realised what it was he *actually* wanted about ten seconds ago. Ya beat me to it :P

	-- Daniel
January 08, 2007
torhu wrote:
> Lutger wrote:
>> Hi, I need to convert a uint to 4 ubytes in big endian order for which I have written the function below. The thing is, I'm not 100% sure it is correct for Big Endian systems, would somebody be so kind as to inform me if this will work?
>>
>> void concatUint(inout ubyte[] bytestream, uint num)
>> {
>>      bytestream.length = bytestream.length + 4;
>>      static if (std.system.endian == Endian.LittleEndian)
>>      {
>>          bytestream[$-4] = num >> 24;
>>          bytestream[$-3] = num >> 16;
>>          bytestream[$-2] = num >> 8;
>>          bytestream[$-1] = num;
>>      }
>>      else // big endian
>>      {
>>          bytestream[$-4] = num;
>>          bytestream[$-3] = num >> 8;
>>          bytestream[$-2] = num >> 16;
>>          bytestream[$-1] = num >> 24;
>>      }
>> }
> 
> 
> Since you haven't done any weird casting, the compiler (or is it cpu?) knows that num is an uint.  So the bit shifting will behave like num is big endian, no matter the endianness of the system.
> 
> In other words, your code for little endian systems is correct for big endian too.  But your big endian code swaps the byte order, resulting in little endian order in bytestream.

That explains a lot, especially why I wasn't able to figure it out! Now I wonder how I have got this weird assumption in my head that it would work different for big / little endian systems.

Thank you very much for clearing this up.
January 11, 2007
Lutger wrote:
> Hi, I need to convert a uint to 4 ubytes in big endian order for which I have written the function below. The thing is, I'm not 100% sure it is correct for Big Endian systems, would somebody be so kind as to inform me if this will work?
> 
> void concatUint(inout ubyte[] bytestream, uint num)
> {
>     bytestream.length = bytestream.length + 4;
>     static if (std.system.endian == Endian.LittleEndian)

torhu is right - your code doesn't need to interrogate the platform byte order.

But for future reference, if you ever do want to write endian-dependent code, you might version (LittleEndian) and version (BigEndian) nicer than examining std.system.endian.

Stewart.
January 11, 2007
Stewart Gordon wrote:
> But for future reference, if you ever do want to write endian-dependent code, you might version (LittleEndian) and version (BigEndian) nicer than examining std.system.endian.
> 
> Stewart.

Cool, I've missed those somehow.