bit fields - Bitfields and C++11 static_assert -


we know bit-fields not portable, , therefore should avoided, quote c99 standard 6.7.2.1/10 - "structure , union specifiers";

an implementation may allocate addressable storage unit large enough hold bitfield. if enough space remains, bit-field follows bit-field in structure shall packed adjacent bits of same unit. if insufficient space remains, whether bit-field not fit put next unit or overlaps adjacent units implementation-defined. order of allocation of bit-fields within unit (high-order low-order or low-order high-order) implementation-defined. alignment of addressable storage unit unspecified.

however; in dealing hardware devices , such, 1 have deal specific bit-layouts, which, without bit-fields, imply nasty , unreadable (at-least in opinion) bit-fiddling code.

so i'd do, use bit-fields, i'd first validate bit-field layout compiler generates, matches expectations. i'm in process of doing, writing static_asserts, fails, in case, layout doesn't match.

for instance; simple size assertion;

struct bitfield {     bool ac     : 1; // accessed bit. set 0. cpu sets 1 when segment accessed.     bool rw     : 1; // readable bit/writable bit. code segment readable / data segment writeable.     bool dc     : 1; // direction bit/conforming bit. 0=the segment grows up. 1=the segment grows down.     bool ex     : 1; // executable bit. if 1 code in segment can executed, ie. code selector. if 0 data selector.     bool dt     : 1; // descriptor type (always 1?).     uint8_t dpl   : 2; // descriptor privilege level, 2 bits. - contains ring level, 0 = highest (kernel), 3 = lowest (user applications).     bool p      : 1; // present bit. - segment present? (1 = yes). must 1 valid selectors. };  static_assert(sizeof(bitfield)==1,  "incorrect size of bitfield"); 

this works charm, , ensures bit-field of correct size, due implementation specific nature of bit-fields, can't assume whether layout inside of bit-field correct. i'm trying is, static_assert layout of bit-field;

// used check bitfield, matches specific required layout union bitfield_layout_checker {        constexpr bitfield_layout_checker(uint8_t raw) : raw(raw) {}      constexpr bitfield getbitfield()     {         return format;     }      uint8_t raw;     bitfield format; };  constexpr bool isbitfieldokay() {     return bitfield_layout_checker(0x01).getbitfield().p == true; }  static_assert(isbitfieldokay(), "bitfield layout not okay"); 

so test, supposed check present bit, in correct place. - when trying compile above code, using gcc v4.8.1 yields, error message;

main.cpp:35:5: error: non-constant condition static assertion      static_assert(isbitfieldokay(), "bitfield layout not okay");      ^ main.cpp:35:34:   in constexpr expansion of ‘isbitfieldokay()’ main.cpp:32:58:   in constexpr expansion of ‘bitfield_layout_checker(1).bitfield_layout_checker::getbitfield()’ main.cpp:35:5: error: accessing ‘bitfield_layout_checker::format’ member instead of initialized ‘bitfield_layout_checker::raw’ member in constant expression 

using clang v3.1 yields, error message;

a.cpp:35:19: error: static_assert expression not integral constant expression     static_assert(isbitfieldokay(), "bitfield layout not okay");                   ^~~~~~~~~~~~~~~~ a.cpp:23:20: note: read of member 'format' of union active member 'raw' not allowed in   constant expression         return format;                ^ a.cpp:23:20: note: in call 'bitfield(1.format)' a.cpp:32:16: note: in call ')'     return bitfield_layout_checker(0x01).getbitfield().p == true;            ^ a.cpp:35:19: note: in call 'isbitfieldokay()'     static_assert(isbitfieldokay(), "bitfield layout not okay");                   ^ 

which indicates i'm not allowed read out format field of union, when has been initialized through raw field. there way around this?

i not recommend using bitfields if wish deal hardware. tagged c++11 have std::bitset makes comfortable access individual bits inside fixed length:

class register { public:     void setac(bool level) { m_register[0] = level; }     bool getac() { return m_register[0]; }      void setrw(bool level) { m_register[1] = level; }     bool getrw() { return m_register[1]; }      /* other setters , getters... */      void setdpl(uint8_t val) {         std::bitset<2> valbits(val);         m_register[5] = valbits[0];         m_register[6] = valbits[1];     }     uint8_t getdpl() {         std::bitset<2> bits;         bits[0] = m_register[5];         bits[1] = m_register[6];         return bits.to_ulong();     }      /* other setters , getters... */      uint8_t getregister() { return m_register.to_ulong(); }  private:     std::bitset<8> m_register; }; 

but can create struct of std::bitset this:

struct bitfield {     std::bitset<1> ac;     std::bitset<1> ac;     std::bitset<1> rw;     std::bitset<1> dc;     std::bitset<1> ex;     std::bitset<1> dt;     std::bitset<2> dpl;     std::bitset<1> p; }; 

the problem second example more complicated assemble , send hardware.


Comments

Popular posts from this blog

php - Calling a template part from a post -

Firefox SVG shape not printing when it has stroke -

How to mention the localhost in android -