在预处理器指令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语句。

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

&的先验度低于!=。因此:

MODE & 2 != 0

与相同

MODE & (2 != 0)

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

MODE & 1

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

(MODE & 2) != 0

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

#if MODE & 2

记住,对于宏名称,更喜欢使用大写名称。

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

不,这听起来完全正常。我会选择更多描述性的名字,然后简单的& 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.

如果可能的话,最好使用C++模板和SFINAE,而不是纯C宏。

我做错了什么?

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

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

否。


我记得Dennis M.Ritchie的部分C语言的发展,从节名Neonatal C开始,他写道:

[…]在从B到C的转换中,需要替换&由&amp;在该声明中;为了减少转换的痛苦,我们决定保留&运算符相对于==相同,并且仅拆分&amp;从&。今天,似乎最好将&和==,从而简化公共C习惯用法:要测试一个掩码值和另一个值,必须编写

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

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

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

相关内容

  • 没有找到相关文章

最新更新