Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What makes this code "endian independent"?

Tags:

c++

c

I came across the following code, and was told that it means that COL_8888_RED is "endian independent". Why? What makes this endian independent? (I have asked the original coder but they're not getting back to me ... heck maybe they don't know either.)

union _colours {
    uint8  c[3][4];
    uint32 alignment;
};

static const union _colours col_8888 = {
        {    /*   B     G     R     A  in memory     */
                {    0x00, 0x00, 0xFF, 0xFF, }, /* red   */
                {    0x00, 0xFF, 0x00, 0xFF, }, /* green */
                {    0xFF, 0x00, 0x00, 0xFF, }, /* blue  */
        }
};

#define COL_8888_RED   *((uint32 *)&col_8888.c[0])
like image 698
BeeBand Avatar asked Sep 02 '10 16:09

BeeBand


3 Answers

This code is not "endian-independent" in a sense that platforms with different endianness will give you different values seen through COL_8888_RED. In other words, in the traditional understanding of endian-dependency this code is as endian-dependent as it ever gets.

A different question is where is that COL_8888_RED is supposed to be used. Maybe it is intended to be passed to some API, which by itself is endian-dependent in the very same way to the point that the endian-dependency of the API cancels out the endian-dependency of COL_8888_RED. In that case everything will work "as intended", i.e. endian-independently. (For example, if the API receives the color value as uint32 and then separates it into the ARGB components by using the same union, it will get the correct original ARGB values regardless of endianness.)

But nevertheless, to say that the value of COL_8888_RED by itself is endian-independent is totally incorrect.

like image 93
AnT Avatar answered Oct 21 '22 14:10

AnT


Arrays of bytes are endianness independent on almost all architectures. By assigning to it as a byte array, the programmer ensures consistent content for the data. The bytes can also be accessed individually on any architecture. If the coder had just made an array of 3 words, machine endianness would play a role in determining the exact layout of the bits.

like image 39
nmichaels Avatar answered Oct 21 '22 16:10

nmichaels


I suppose that COL_8888_RED, as a macro, will always be a uint32, which, as long as the macro COL_8888_RED is always used, the source byte array {0x00,0x00,0xFF,0xFF} will always translate into what the programmer wants to mean as RED.

The definition, then, means you can write the same source code on a big endian, or little endian, machine, and go from a discrete array to a logical colour.

EDIT: why then, not use an enumeration, or a constant like "1"?

Probably, the original API developer wanted to be able to point to another location of {0x00,0x00,0xFF,0xFF} in memory, so that code like the following could be written:

uint8 *p = malloc( sizeof(uint8)*4 );

fread( p, sizeof(uint8), 4, inBuff );

if( *((uint32 *)p) == COL_8888_RED )
{
    printf( "I read red!\n" );
}
like image 21
maxwellb Avatar answered Oct 21 '22 16:10

maxwellb