Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defining bitfields according to endianness at compile time

Tags:

c++

endianness

Lets say I have the following 2 structures based upon 2 bytes:

#pragma pack(1)
struct Foo {
    unsigned short a : 5;
    unsigned short b : 4;
    unsigned short c : 2;
    unsigned short d : 5;
} ;

struct Bar {
    unsigned short a : 5;
    unsigned short b : 4;
    unsigned short c : 2;
    unsigned short d : 3;
    unsigned short e : 2;
} ;

And I have a union which containes them:

union Baz {
    unsigned short val;
    struct Foo foo;
    struct Bar bar;
} ;

And then in my program I can put a value using val, and get a, b, c, d and e values according to the their bitfields, no bitwise operations/interfaces and more required.

The problem though, is that I need it to support both big and little endianness, which means that I need to have my struct define the bitfields according to the endianness at compile time.

Thus, I need something like this:

#pragma pack(1)
#if BIG_ENDIAN
struct Foo {
    unsigned short a : 5;
    unsigned short b : 4;
    unsigned short c : 2;
    unsigned short d : 5;
} ;

struct Bar {
    unsigned short a : 5;
    unsigned short b : 4;
    unsigned short c : 2;
    unsigned short d : 3;
    unsigned short e : 2;
} ;

#else
struct Foo {
    unsigned short d : 5;
    unsigned short c : 2;
    unsigned short b : 4;
    unsigned short a : 5;
} ;

struct Bar {
    unsigned short e : 2;
    unsigned short d : 3;
    unsigned short c : 2;
    unsigned short b : 4;
    unsigned short a : 5;
} ;
#endif

I tried looking this up and all I could find is either a runtime check or compiled values which can only be used at runtime. I know that there are many macros like BYTE_ORDER, LITTLE_ORDER, BIG_ORDER and more, but I cannot ensure they will be defined in the requested deployed environment, as well as the endian.h header files. Also, as far as I know, boost's endian.hpp is implementing what i stated above regarding the macros, so I am not certain it will make any difference..

Any suggestions?


edit1: In reply to one of the comments: I need a c++03 solution, but a c++11/14 one would also be nice for enlightenment.

like image 920
Gulzar Avatar asked Nov 10 '22 01:11

Gulzar


1 Answers

The question is too long for a simple short question: 'How do I know endiannes during compile time.', and regretfully, the answer to this question is 'You can not'.

The thing is, neither Posix, nor C/C++ standard specify anything in regards to endianness. The only thing you can do is to test for known architecture-specific macros and derive enddiannes from it.

like image 118
SergeyA Avatar answered Nov 14 '22 21:11

SergeyA