有没有直观的方法来检查标志和状态?

时间:2012-11-02 23:19:16

标签: c++ enums flags enum-flags bitflags

无法找到我案件的相关答案,所以我会尝试解释我的情况:

我有以下代码:

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
 }

我的代码用于lexing一个文档,我只是在我不在注释块中时才尝试执行操作。问题是,当我不在评论中时,上述陈述正好相反...

以下陈述正确地完成了工作,但似乎违反直觉:

if (lexStatus & fInCommentBlock == fInCommentBlock)

所以问题是:

  • 为什么?为什么它与我期待的完全相反?

由于运营商优先级if ((lexStatus & fInCommentBlock) != fInCommentBlock)解决了问题

  • 我接近正确的方法吗?
  • 有更好的方法吗?
  • 有没有办法确保每个标志都有不同的值?

最后一个问题是因为某些原因lexStatus & fInCommentBlock因为某些位置设置,即使我没有将它们设置在代码中的任何位置......

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:4)

解决您的第一个问题:您的问题是运算符优先级以及对按位运算符如何工作的理解。

if (lexStatus & fInCommentBlock == fInCommentBlock)

这仅适用于您,因为==的优先级高于&,因此fInCommentBlock == fInCommentBlock始终为true,因此与lexStatus & 1相同,这与lexStatus & OnlySpaceslexStatus == 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))

哪个会更直观。