Маски битового поля в C

Я соглашаюсь с Justin, в то время как большинство технических людей будет использовать копию, метод вклеивания, для менее опытных пользователей это - хорошая практика.

Еще одна вещь, которую я добавил бы, состоит в том, что второму полю нужно отключить функцию автоматического заполнения. Это гарантирует, что существует человеческий вход из любого метода на по крайней мере одном из полей.

5
задан Grandpa 10 October 2009 в 21:35
поделиться

5 ответов

Or, if you really wanted the 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
ответ дан 14 December 2019 в 08:55
поделиться

I don't know how to do it at compile time, but at runtime it should be a simple matter of union'ing an instance of your bitfield struct with an appropriately-sized unsigned int, and setting all fields to 0 except the one you care about which should be set to all 1s -- the value of the unsigned int is then the bitmask you want. You can do it for each field at startup, maybe with a macro to avoid some repetitive code. Might not that suffice?

2
ответ дан 14 December 2019 в 08:55
поделиться

Yes, this can be done. You need to capture the value and do the operation. Then you need to use an atomic compare and swap (like InterlockedCompareExchange on Windows) to store the new value if the memory still contains the old value. If someone modified the value, you loop and try again. Note this is a standard pattern for doing any operation on a word-sized piece of data where an intrinsic isn't available.

The code below uses an int - as Keith pointed out you can use a union to be able to get the values of the struct as an int.

int oldValue, newValue;
do
{
    oldValue = myRef;
    newValue = oldValue & ~AGE_MASK;
} while (InterlockedCompareExchange(&myRef, newValue, oldValue) != oldValue);
0
ответ дан 14 December 2019 в 08:55
поделиться

I don't think is possible - even with offsetof() which works for byte offsets but does not seem to work for bitfields. I would redeclare the fields as enums/defines (0x01 0x02 etc) and manage the bits yourself, so you can get your atomic changes.

1
ответ дан 14 December 2019 в 08:55
поделиться

You could do something like:

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

To atomically clear a field of myRef, 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);

(+ unshown code to handle when compare_and_swap fails)

2
ответ дан 14 December 2019 в 08:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: