Есть ли интуитивно понятный способ проверки флагов и состояний?

Не удалось найти соответствующий ответ на мой случай, поэтому я попытаюсь объяснить мою ситуацию:

У меня есть следующий код:

enum Flags {
OnlySpaces      = 1 <<  0,

valComment      = 1 <<  1,
valCommentBlock = 1 <<  2,
valLabelName    = 1 <<  3,
valVariableName = 1 <<  4,
valFunctionName = 1 <<  5,

invSyntax       = 1 << 32,

fInVarLab       = valLabelName|valVariableName,
fInIdentifier   = valLabelName|valVariableName|valFunctionName,
fInCommentBlock = OnlySpaces|valCommentBlock,

initState       = OnlySpaces|fInIdentifier|valComment,
};

int lexStatus = initState;

for (int i = 0; sc.More(); sc.Forward(), i++) {

if (sc.atLineStart) {
if (lexStatus & fInCommentBlock != fInCommentBlock) // Here is the problem
sc.SetState(DEFAULT);

lexStatus = initState;
}
... // More code
}

Мой код предназначен для лексизации документа, и я пытаюсь выполнить действие только тогда, когда я НЕ в блоке комментариев. Дело в том, что вышеприведенное утверждение возвращает прямо противоположное, когда я не в комментарии …

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

if (lexStatus & fInCommentBlock == fInCommentBlock)

Итак, вопросы:

  • Зачем? Почему это действует совершенно противоположно тому, что я ожидаю?

Из-за приоритета оператора if ((lexStatus & fInCommentBlock) != fInCommentBlock) решает проблему

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

Последний вопрос добавлен, потому что по какой-то причине lexStatus & fInCommentBlock потому что некоторые биты установлены, хотя я не устанавливаю их нигде в коде …

Заранее спасибо за помощь!

1

Решение

Чтобы ответить на ваш первый вопрос: ваша проблема — приоритет операторов и понимание того, как работают побитовые операторы.

if (lexStatus & fInCommentBlock == fInCommentBlock)

Это работает для вас только потому, что == имеют более высокий приоритет, чем & так fInCommentBlock == fInCommentBlock всегда верно, следовательно, то же самое, что lexStatus & 1, что то же самое, что lexStatus & OnlySpaces, Это будет верно, когда lexStatus == initState так как initState включает флаг OnlySpaces,

Есть ли способ лучше?

Вы хотите абстрагировать побитовое сравнение в одну или две вспомогательные функции.

int LexStatus_Is(int flags) { return (lexStatus & flags) == flags; }
int LexStatus_IsNot(int flags) { return (lexStatus & flags) != flags; }

Тогда вы можете написать:

if (LexStatus_IsNot(fInComment))

Который был бы более интуитивным.

4

Другие решения

Других решений пока нет …