Не удалось найти соответствующий ответ на мой случай, поэтому я попытаюсь объяснить мою ситуацию:
У меня есть следующий код:
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
потому что некоторые биты установлены, хотя я не устанавливаю их нигде в коде …
Заранее спасибо за помощь!
Чтобы ответить на ваш первый вопрос: ваша проблема — приоритет операторов и понимание того, как работают побитовые операторы.
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))
Который был бы более интуитивным.
Других решений пока нет …