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

Meh*_*azi 0 c++ directive arduino comparison-operators c-preprocessor

我想根据常量值定义一些函数:

#define mode 5

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

#if mode & 4 != 0
  // function 2
#endif
Run Code Online (Sandbox Code Playgroud)

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

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

Kam*_*Cuk 5

&那么 的优先级较低!=。所以:

MODE & 2 != 0
Run Code Online (Sandbox Code Playgroud)

是相同的

MODE & (2 != 0)
Run Code Online (Sandbox Code Playgroud)

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

MODE & 1
Run Code Online (Sandbox Code Playgroud)

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

(MODE & 2) != 0
Run Code Online (Sandbox Code Playgroud)

检查第二位是否已设置。但实际上只是删除该!=部分并执行以下操作:

#if MODE & 2
Run Code Online (Sandbox Code Playgroud)

请记住,宏名称应优先使用大写字母

这听起来和看起来都很奇怪

不,这听起来完全正常。我会使用更多描述性的名称,然后简单的& 2-神奇的数字会令人困惑。喜欢:

#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.
Run Code Online (Sandbox Code Playgroud)

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

我究竟做错了什么?

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

我是否想做一件愚蠢或不可能的事情?

不。


我记得Dennis M. Ritchie 的《C 语言的开发》部分,从章节名称中Neonatal C他写道:

[...] 在从 B 转换为 C 时,需要在这样的语句中将 & 替换为 &&;为了使转换不那么痛苦,我们决定保持 & 运算符相对于 == 的优先级相同,并且只是将 && 的优先级与 & 稍微分开。今天,似乎最好移动 & 和 == 的相对优先级,从而简化一个常见的 C 习惯用法:要针对另一个值测试屏蔽值,必须编写

if ((a&mask) == b) ...
Run Code Online (Sandbox Code Playgroud)

其中需要内括号但很容易被忘记。

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