Работа с 8-битными целыми числами в качестве маски флага - PullRequest
2 голосов
/ 11 июля 2019

У меня есть 65 различных флагов (опций) для пользовательской структуры данных. В настоящее время это выглядит так:

struct CustomDataStruct {
    int Something;
    unsigned char Flags[9]
};

Таким образом, я могу хранить до 72 флагов (7 оставшихся на всякий случай, если я решу добавить еще). Я хочу использовать отдельный бит для каждого флага, поэтому я придумал это:

void SetFlag(struct CustomDataStructure* Struct, int FlagNr) {
    // Error checking and other stuff here
    int index = FlagNr / 8; array.
    Struct->Flags[index] |= 1 << (__________);

}

Я уже пробовал с 1 << (FlagNr % 8), но он не устанавливает правильный бит. Например, я хочу включить флаг ID 23 (начиная с нуля), поэтому я вызываю SetFlag(structInstance, 23), который правильно определяет индекс (Flags [2]), но 23 % 8 = 7 и 1 << 7 = 1000 0000 (в двоичном виде) вместо правильного значения, которое должно быть 0000 0001 (включить последний бит 3-го числа массива, т. Е. Бит № 24).

Флаги должны храниться в этом массиве, каждый бит представляет переключатель флага. Изменить это не вариант.

Ответы [ 3 ]

3 голосов
/ 11 июля 2019

Вместо того, чтобы сдвигать бит, поиск массива работает легко.FlagNr содержит индекс на основе нуля, поэтому значение 0 - это первый бит в первом элементе массива.

void setFlag( struct CustomDataStructure* thing, int FlagNr) {
    static uint8_t  masks[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
    size_t   index = FlagNr % 8;
    size_t   xndex = FlagNr / 8;
    thing->Flags[xndex] |= masks[index];
}
3 голосов
/ 11 июля 2019

Биты обычно индексируются, начиная с наименее значимого (крайнего правого) бита, поскольку в большинстве случаев это имеет больше смысла.Если вы хотите изменить это, просто сделайте 1 << (7 - FlagNr % 8) или 0x80 >> (FlagNr % 8).

1 голос
/ 11 июля 2019
void setFlag( struct CustomDataStructure* foo, int flagIndex ) {

    assert( flagIndex >= 0 && flagIndex < 72 ); // Defensive programming!

    size_t arrayIndex = flagIndex / 8;
    int    bitShift   = flagIndex % 8;

    // If you want reverse (little-endian) bit order then subtract from 7:
    bitShift = 7 - bitShift;

    // This code is expanded for readability. An optimizing-compiler will still generate fast code:
    uint8_t flags = foo->Flags[ arrayIndex ];
    flags = flags | ( 1 << bitShift );
    foo->Flags[ arrayIndex ] = flags;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...