Search code examples
c++linuxvxworks

Determine byte order of uint32_t


I am converting a vxWorks application to Linux.

Previously, I had a union with a word and a struct so that when I accessed the members of the struct, I could use the word's layout to build my struct members.

However, I don't recall how I figured this out and it works on the vxWorks box. On my vxWorks instance, the layout is:

typedef union Status
{
    struct fields
    {
        uint32_t byteA : 1; // <31>
        uint32_t blank : 23; // <30:8>
        uint32_t bytesN : 8; // <7:0>
    } fields;

    uint32_t word;
}

I've already ran into some endian issues while porting from vxWorks to Linux. So figuring out the layout of uint32_t on linux is important.


Solution

  • From your comment to the other answer, you want whatever is stuffed into the word member of the union to appear in the fields.bytesN member. To achieve this you must either have some kind of pre-build process that lays out the field bit fields appropriately after detecting machine endianness, or create 2 structures, one for big endian and the other for little endian.

    typedef union Status
    {
        struct fieldsBE
        {
            uint32_t byteA : 1; // <31>
            uint32_t blank : 23; // <30:8>
            uint32_t bytesN : 8; // <7:0>
        } fieldsBE;
    
        struct fieldsLE
        {
            uint32_t bytesN : 8; // <7:0>
            uint32_t blank : 23; // <30:8>
            uint32_t byteA : 1; // <31>
        } fieldsLE;
    
        uint32_t word;
    };
    
    int main()
    {
      bool isBigEndian = DetectEndianness(); // returns true if big endian
    
      Status status;
    
      status.word = 40;
    
      if( isBigEndian ) {
        uint8_t bytesN = status.fieldsBE.bytesN;
    
      } else {
        uint8_t bytesN = status.fieldsLE.bytesN;
    
      }
    }
    

    Of course, if you only want to support little endian in your port use the layout of fieldsLE instead of the original layout you've shown.