Converting Endianess on a bit field structure

前端 未结 8 668
心在旅途
心在旅途 2021-02-02 03:48

I need to convert a bit-field structure from little-endian to big-endia architecture. What is the best way to do that, as there will be issues in byte boundaries, if I simply sw

相关标签:
8条回答
  • 2021-02-02 04:08

    In a project porting code from MIPS to Linux/x86 we did like this.

    struct {
    
    #ifdef __ONE_ENDIANESS__
        unsigned int    b1:1;
        unsigned int    b2:8;
        unsigned int    b3:7;
        unsigned int    b4:8;
        unsigned int    b5:7;
        unsigned int    b6:1;
    #define _STRUCT_FILLED
    #endif /* __ONE_ENDIANESS__ */
    
    #ifdef __OTHER_ENDIANESS__
        unsigned int    b6:1;
        unsigned int    b5:7;
        unsigned int    b4:8;
        unsigned int    b3:7;
        unsigned int    b2:8;
        unsigned int    b1:1;
    #define _STRUCT_FILLED
    #endif /* __OTHER_ENDIANESS__ */
    
    };
    
    #ifndef _STRUCT_FILLED
    #  error Endianess uncertain for struct
    #else
    #  undef _STRUCT_FILLED
    #endif /* _STRUCT_FILLED */
    

    The macros __ONE_ENDIANESS__ and __OTHER_ENDIANESS__ was the appropriate for the compiler we used so you might need to look into which is appropriate for you...

    0 讨论(0)
  • 2021-02-02 04:10

    It should be enough to swap the bytes. Bit position within a byte is the same in big and little endian.
    e.g. :

    char* dest = (char*)&yourstruct;
    unsigned int orig = yourstruct;
    char* origbytes = (char*)&orig;
    dest[0] = origbytes[3];
    dest[1] = origbytes[2];
    dest[2] = origbytes[1];
    dest[3] = origbytes[0];
    
    0 讨论(0)
  • 2021-02-02 04:11

    Processor endianness is unrelated to bit field ordering. It's quite possible to have two compilers on the same computer use opposite ordering for bitfields. So, given this:

    union {
        unsigned char x;
        struct {
            unsigned char b1 : 1;
            unsigned char b2 : 7;
        };
    } abc;
    abc.x = 0;
    abc.b1 = 1;
    printf( "%02x\n", abc.x );
    

    Unless you happen to have detailed documentation, the only way to know whether that will print out 01 or 80 is to try it.

    0 讨论(0)
  • 2021-02-02 04:15

    To get this going I finally got a solution (some what derived from epatel's solution above). This is if I convert from x86 to Solaris SPARC.

    We need to first swap the incoming sturcture and then read the elements in reverse order. Basically after looking at how the structures are alligned I saw that the endianess changed both in byte ordering and bit ordering. Here is a pseudo code.

    struct orig
    {    
        unsigned int    b1:1;
        unsigned int    b2:8;
        unsigned int    b3:7;
        unsigned int    b4:8;
        unsigned int    b5:7;
        unsigned int    b6:1;
    };
    
    struct temp
    {    
        unsigned int    b6:1;
        unsigned int    b5:7;
        unsigned int    b4:8;
        unsigned int    b3:7;
        unsigned int    b2:8;
        unsigned int    b1:1;
    }temp;
    
    
    func (struct orig *toconvert)
    {
        struct temp temp_val;
        //Swap the bytes
        swap32byte((u32*)toconvert);
        //Now read the structure in reverse order - bytes have been swapped
        (u32*)&temp_val = (u32 *)toconvert;
        //Write it back to orignal structure
        toconvert->b6=temp_val.b6;
        toconvert->b5=temp_val.b5;
        toconvert->b4=temp_val.b4;
        toconvert->b3=temp_val.b3;
        toconvert->b2=temp_val.b2;
        toconvert->b1=temp_val.b1;
    

    }

    After some experimenting I found that this approach is only valid if the elements completely fill the structure, i.e. there are no unused bits.

    0 讨论(0)
  • 2021-02-02 04:18

    You have two 16 bit sections there (the first three fields and the last three fields are 16 bits).

    That's only 65536 entries. So have a lookup table that holds the bit-reversed version of the fields. Wrap the struct in a union with another struct that has two 16 bit fields to make this easier?

    Something like (untested, I'm not near a C compiler):

    union u {
        struct {
            unsigned int    b1:1;
            unsigned int    b2:8;
            unsigned int    b3:7;
            unsigned int    b4:8;
            unsigned int    b5:7;
            unsigned int    b6:1;
         } bits;
         struct {
            uint16 first;
            uint16 second;
         } words
    } ;
    
    unit16 lookup[65536];
    
    /* swap architectures */
    
    void swapbits ( union u *p)
    {
       p->words.first = lookup[p->words.first];
       p->words.second = lookup[p->words.second];
    }
    

    Population of the lookup table left as an exercise for the reader :)

    However, read your compiler doc carefully. I'm not sure if the C standard requires that struct to fit in a word (although I'd expect most compilers to do that).

    0 讨论(0)
  • 2021-02-02 04:19

    You should not use bit-fields when the physical layout is important because it is implementation-defined in which order the larger word is populated.

    0 讨论(0)
提交回复
热议问题