在预处理器指令 C++ 中使用比较运算符

Using Comparison Operators in preprocessor directives C++

我想定义一些基于常数值的函数:

#define mode 5

#if mode & 2 != 0
  // function 1
#endif

#if mode & 4 != 0
  // function 2
#endif

这听起来和看起来很奇怪,但我想使用一个常量来定义和激活一些程序模块。
定义 mode = 2 包括函数 1,mode = 4 包括函数 2,mode = 6 包括两个函数。
存在一个问题:==!=>< 等比较运算符似乎在指令中不起作用,并且总是执行 #if 语句。

我做错了什么?我是不是想做一件愚蠢或不可能的事情?

&precendence 低于 !=。所以:

MODE & 2 != 0

相同
MODE & (2 != 0)

2 != 0逻辑上为真,所以!=运算符的结果是1。因此这与

相同
MODE & 1

它只是检查第一位。当你想要的时候:

(MODE & 2) != 0

检查是否设置了第二位。但实际上只需删除 != 部分并执行:

#if MODE & 2

记得prefer upper case names for macro names.

This may sound and look weird

不,这听起来很正常。我会使用更多描述性的名称,然后普通的 & 2 - magic numbers 会令人困惑。喜欢:

#define MODE  (MODE_ENABLE_FUNC_1 | MODE_ENABLE_FUNC_2)

#define MODE_ENABLE_FUNC_1  (1<<0)
#define MODE_ENABLE_FUNC_2  (1<<1)
#define MODE_ENABLE_FUNC_3  (1<<2)
#define MODE_IS_ENABLED(mode, feature) ( ((mode) & (feature)) != 0)
#if MODE_IS_ENABLED(MODE, MODE_ENABLE_FUNC_1)
// etc.

如果可能,更喜欢使用 C++ 模板和 SFINAE,而不是普通的 C 宏。

What am I doing wrong?

您假设 != 的优先级低于 &

Am I trying to do a stupid or impossible thing?

没有


我记得 The development of C language by Dennis M. Ritchie 部分和章节名称 Neonatal C 他写道:

[...] In converting from B to C, one wants to replace & by && in such a statement; to make the conversion less painful, we decided to keep the precedence of the & operator the same relative to ==, and merely split the precedence of && slightly from &. Today, it seems that it would have been preferable to move the relative precedences of & and ==, and thereby simplify a common C idiom: to test a masked value against another value, one must write

if ((a&mask) == b) ...

where the inner parentheses are required but easily forgotten.

不用担心 - 您不是第一个也不是最后一个忘记 & 和另一个运算符上下文中的大括号的人。