C ++ - connection data structure, easy accessibility of bits in DWORD

I'm working through the DirectX online tutorial suite and I have the following structure:

struct CUSTOMVERTEX
{
FLOAT x, y, z, rhw; // from the D3DFVF_XYZRHW flag
DWORD color;        // from the D3DFVF_DIFFUSE flag
}

      

My basic understanding of directX leads me to color being composed of 8-bit alpha, red, green and blue channels.

I am trying to get eastern access to these channels. Instead of writing the following code multiple times (in a CUSTOMVERTEX structure):

public: int red()
{
    return (color & 0x00FF0000) >> 16;
}

      

I could write a more elegant word with a combination of union and structure, for example.

struct CUSTOMVERTEX
{
    FLOAT x, y, z, rhw; // from the D3DFVF_XYZRHW flag

    #pragma pack(2)
    union 
    {
        DWORD color;        // from the D3DFVF_DIFFUSE flag

        struct
        {
            char a;
            char r;
            char g;
            char b;
        };
    };
}

      

However, this does not appear to function as expected, the values ​​in r, g and b almost seem to be the opposite of the colors, for example. if color is 0x12345678 a = 0x78, r = 0x56. Is this an enzyme problem?

And what other problems can I expect from this solution? e.g. overflow from color elements?

I guess what I'm asking ... is there a better way to do this?

+2


a source to share


3 answers


Yes, this is a problem with enthiancy. If you only support one platform, you can lay out the structure elements according to the architecture content. If you are dealing with multiple architectures, you will need to #define multiple entity-specific element structure layouts.

Structs and unions always look more elegant to me, but bitwise operations are the more portable of the two. When I do this, I stick with my startup code to make sure the structure is the size I expect it to be before the undefined nasty thing happens.



In C ++, you can write a class that encapsulates your data and performs your operations for you.

+2


a source


If your DWORD color is 0x12345678, the byte at & color is 0x78 on little-endian system.



The union trick technically leads to undefined behavior. What's wrong with the accessor method?

+1


a source


To create a union job to do this, you need to make sure you have endianess issues and you need to make sure the filling issues are correct (which will require non-standard operators #pragma

or such). Even if you are not interested in portability (DirectX is Windows only), I would still suggest that you use built-in functions for this purpose. You may need a few very similar ones, but I can argue that the added complexity of these few functions is still less than union

. It will probably be easier for them to get right, you will be less likely to break (especially if you break quietly) if you change the compilers, and it will be easier for the next guy reading the code to be sure they are doing what he expects.

As an aside - why did you use #pragma pack(2)

instead #pragma pack(1)

?

And if you do #pragma pack

, remember to "save and restore" the original package settings so that other things don't behave unexpectedly:

#pragma pack(push)
#pragma pack(2)
//...
#pragma pack(pop)

      

+1


a source







All Articles