Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Structures with bitwise data in C++ [duplicate]

Possible Duplicate:
Converting Bit Field to int

I am working on an application, part of which handles 16-bit words that contain a number of 1-bit flags. I am handling the data using a structure similar to the one shown below:

struct mystruct
{
   uint16_t Reserved1   :3;
   uint16_t WordErr     :1;
   uint16_t SyncErr     :1;
   uint16_t WordCntErr  :1;
   uint16_t Reserved2   :10;
};

i.e. the structure contains a single 16-bit variable that is handled as a number of smaller (in some cases, 1-bit flag) pieces.

My question is this, is there a simple way to handle the entire 16-bit word as one value, say, to output it to the console, or a file, or add it to another data structure? I don't know of any way of doing this besides shifting the individual structure elements and adding them to a temporary uint16_t variable. It seems that there is probably a simpler way of extracting the entire word, but I can't find any information on how the compiler handles a structure like this.

EDIT: I suppose this may be obvious but what I am trying to do in a nutshell is be able to access the 1-bit flags individually, as well as use the structure as a single variable of type uint16_t (i.e. unsigned short, 16 bits).

like image 214
Joel M. Avatar asked Sep 18 '12 18:09

Joel M.


1 Answers

The standard approach here is to use anonymous structs/unions, like this:

union mystruct
{
   struct
   {
      uint16_t Reserved1   :3;
      uint16_t WordErr     :1;
      uint16_t SyncErr     :1;
      uint16_t WordCntErr  :1;
      uint16_t Reserved2   :10;
   };

   uint16_t word_field;
};

or, if union is not good as a top level object,

struct mystruct
{
   union
   {
       struct
       {
          uint16_t Reserved1   :3;
          uint16_t WordErr     :1;
          uint16_t SyncErr     :1;
          uint16_t WordCntErr  :1;
          uint16_t Reserved2   :10;
       };

       uint16_t word_field;
   };
};

This definition allows direct access to the inner fields, like:

mystruct s1;
s1.WordCntErr = 1;

Strictly speaking, compiler is not giving any guarantees on how different members of the union will overlap each other. It can use different alignments and even shifts. A lot of people here will readily point this out. Nevertheless, looking at this from the practical standpoint, if all fields of the union have the same size you can safely assume that they occupy the same piece of memory. For example, the code

s1.word_field = 0;

will zero out all bit fields. Tons of code are using this. It is unthinkable this will ever stop working.

like image 94
Kirill Kobelev Avatar answered Sep 23 '22 06:09

Kirill Kobelev