Bitfield masks in C

Is there a portable way in C to find out the mask for a bit field at compile time?

Ideally, I would like to atomically clear a field like this:

struct Reference {
    unsigned age : 3;
    unsigned marked : 1;
    unsigned references : 4;
};

struct Reference myRef;
__sync_and_and_fetch(&myRef, age, ~AGE_MASK);

Otherwise, I have to unlock the structure, which will be more heavy than I would like.

+5
source share
5 answers

Or if you really need a mask:

union Reference {
  unsigned asWord;
  struct {
    unsigned age : 3;
    unsigned marked : 1;
    unsigned references : 4;
  } asFields;
}

Reference agemask_ref;
agemask_ref.asFields = (typeof(agemask_ref.asFields)){0, -1, -1};
unsigned agemask = agemask_ref.asWord;
+2
source

You can do something like:

union Reference {
  unsigned asWord;
  struct {
    unsigned age : 3;
    unsigned marked : 1;
    unsigned references : 4;
  } asFields;
}

To atomically clear myRef field do

union Reference myRef;

union Reference oldr = myRef;
union Reference newr = oldr;
newr.asFields.age = 0;
compare_and_swap(&myRef.asWord, oldr.asWord, newr.asWord);

(+ non-displayable code to handle if compare_and_swap fails)

+2
source

, , int 0, , , 1s - unsigned int - , . , , , . , ?

+2

, - offsetof(), , , , . enums/define (0x01 0x02 ..) , .

+1

, . . (, InterlockedCompareExchange Windows), , - . - , . , , .

The code below uses int, as Kate pointed out, you can use union to be able to get struct values ​​as int.

int oldValue, newValue;
do
{
    oldValue = myRef;
    newValue = oldValue & ~AGE_MASK;
} while (InterlockedCompareExchange(&myRef, newValue, oldValue) != oldValue);
0
source

All Articles