Индексация переменной без выхода за границы перечисления

int8_t state;

enum light_state {OFF, White, Red, Blue, Green, Pink, Color, Random};

// Событие может происходить до 100 000 раз.
//
// Flag выставлен, как сделать переменную, чтоб глубина
// (длина) была Enum?
//
// Или light_state использовать для контроля состояния:
//
//     0, __, __, __|> __, __, 7 — и дальше по кругу
//
// Как я понял из литературы, перечисление — это список указателей
// искомой длины на CONST INDEX[CONST МАСИВОВ[]].
//
// lite <= light_st можно ли light_st++ ??????????????????? 7>>++>>0
if (event)
    state++;

Создавать переменную в 3-бит можно, но не всегда, если число 191. Битовую маску накладывать на каждой итерации и проверять переполнение.

Может, я что-то не знаю? Подскажите.

Type_def_типа enum{...} переменная State той же глубины.


Ответы (1 шт):

Автор решения: eanmos

Есть несколько вариантов.

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

    state = (state + 1) & 0x111;
    

    Такой вариант подойдет только если в перечислении 2N − 1 элементов, зато это самый быстрый вариант — все выражение компилируется всего в 4 инструкции:

    movzx   eax, BYTE PTR state[rip]
    add     eax, 1
    and     eax, 17
    mov     BYTE PTR state[rip], al
    
  2. Использовать оператор взятия остатка от деления %:

    state = (state + 1) % StatesCount;
    

    Если в перечислении 2N − 1 элементов, то компилятор оптимизирует так, что все это считается без деления обычным побитовым сдвигом:

    movzx   eax, BYTE PTR state[rip]
    movzx   eax, al
    add     eax, 1
    cdq
    shr     edx, 29
    add     eax, edx
    and     eax, 7
    sub     eax, edx
    mov     BYTE PTR state[rip], al 
    
  3. Использовать условие:

    state = (state == StatesCount - 1) ? 0 : state + 1;
    

    Обычно, ветвление плохо сказывается на производительности, но как вариант можно сделать и так.


† Думаю, не стоит говорить что нумерация элементов перечисления должна начинаться с 0, а номер каждого следующего элемента должен быть на 1 больше предыдущего.

→ Ссылка