Лучший способ установить флаги


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

  1. Представление флага составляет скрыта.
  2. Следующие методы (или та же идея, по крайней мере): setFlag(structWithFlags *, ACTION_FLAGS ), isFlagSet(structWithFlags *, ACTION_FLAGS) и removeFlag(structWithFlags *, ACTION_FLAGS)
  3. Структура не должна содержать "магическое число", которое определяет размер флага байт, поскольку количество флагов может изменяться при компиляции для различных проектов.

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

В настоящее время, мой способ для достижения этого заключается в следующем:

projectSpecificNeeds.ч:

typedef enum ACTION_FLAGS {
    ACTION_FLAG_NO_1,
    ACTION_FLAG_NO_2,
    //.. etc.
    FLAG_LAST
}ACTION_FLAGS ;

genericModuleThatServesEveryBody.с:

#include <limits.h>
#include "projectSpecificNeeds.h"
typedef struct structWithFlags {
    // Some irrelevant fields
    // each flag is represented by one bit in the flagByte array
    char flagBytes[FLAG_LAST / CHAR_BIT + 1];
}structWithFlags ;

structWithFlags * getStructWithFlags() {
    return calloc(sizeof(structWithFlags));
}

// Bitwise OR between the relevant flag byte and the flag
void setFlag(structWithFlags * st, ACTION_FLAGS flag) {
    st->flagBytes[flag / CHAR_BIT] |= 1 << (flag % CHAR_BIT);
}

// return the AND between the relevant flag byte and the flag 
char isFlagSet(structWithFlags * st, ACTION_FLAGS flag) {
    return st->flagBytes[flag / CHAR_BIT] & ( 1 << (flag % CHAR_BIT));
}

// Bitwise AND between the relevant flag byte all bits except of the flag
void removeFlag(structWithFlags * st, ACTION_FLAGS flag) {
    st->flagBytes[flag / CHAR_BIT] &= ~(1 << (flag % CHAR_BIT));
}

Он хорошо работает, и я не встретил никаких проблем с ним до сих пор. Но мне интересно, есть ли более изящный / чтения еще памяти экономя способ реализации этой функции.



280
5
c
задан 8 декабря 2011 в 11:12 Источник Поделиться
Комментарии
1 ответ

Сколько флагов нужно? Если вы можете довольствоваться только 32 или 64 разными флагами вместо универсального-длина массива флагов, то вероятно было бы лучше выделять флаги в простой неподписанный долго, чтобы сохранить программу из расчета времени.

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

Ваш код только один флаг установлен на время. Распространенный способ, чтобы написать код вроде этого от абонента сторона setFlag (&the_struct, FLAG_THIS | FLAG_THAT);. Весь API-интерфейса Windows использует флаги с побитовое или. Если вы хранили флаги в беззнаковый Long это не будет проблемой, так как вам не нужно, чтобы индекс массива флаг. Затем звонивший не нужно вызвать функцию снова и снова, чтобы установить несколько флагов одновременно.

Конечно, это должно быть хорошо для группы флагов в 32/64 разрядные переменные, связанные с конкретными модуля код?

6
ответ дан 9 декабря 2011 в 02:12 Источник Поделиться