宏 if 语句返回错误:运算符“&&”没有正确的操作数

ila*_*sch 5 c macros c-preprocessor

我正在许多 linux 机器上编译我的代码,在特定机器上,我收到以下错误:

error: operator '&&' has no right operand
Run Code Online (Sandbox Code Playgroud)

宏代码为:

#if LINUX_VERSION_CODE == KERNEL_VERSION(3,12,49) && KERNEL_PATCH_LEVEL == 11
Run Code Online (Sandbox Code Playgroud)

其中 LINUX_VERSION_CODE 和 KERNEL_VERSION 在 linux 源代码中定义,而 KERNEL_PATCH_LEVEL 在我的 Makefile 中定义

KERNEL_PATCH_LEVEL :=$(word 1, $(subst ., ,$(word 2, $(subst -, ,$(KERNEL_HEADERS)))))
Run Code Online (Sandbox Code Playgroud)

如果我将代码更改为 2 行,就像这样,它可以工作

#if LINUX_VERSION_CODE == KERNEL_VERSION(3,12,49) 
#if KERNEL_PATCH_LEVEL == 11
  ...
#endif //KERNEL_PATCH_LEVEL == 11
#endif 
Run Code Online (Sandbox Code Playgroud)

是否有可能仍然保留一个 #if ?我使用 gcc 版本 4.9.0 (Debian 4.9.0-7)

以下宏不起作用:

#if (LINUX_VERSION_CODE == KERNEL_VERSION(3,12,49)) && (KERNEL_PATCH_LEVEL == 11)  

#if ((LINUX_VERSION_CODE == KERNEL_VERSION(3,12,49)) && (KERNEL_PATCH_LEVEL == 11))  

#if defined(KERNEL_MAJOR) && defined(KERNEL_MINOR) && defined(KERNEL_MICRO) && defined(KERNEL_PATCH_LEVEL) && defined(KERNEL_VERSION) && 
defined(LINUX_VERSION_CODE) && \
     (LINUX_VERSION_CODE == KERNEL_VERSION(3,12,49)) && (KERNEL_PATCH_LEVEL == 11)
Run Code Online (Sandbox Code Playgroud)

Jea*_*bre 3

事实证明,错误源是KERNEL_PATCH_LEVEL在 makefile 中定义的但为空。

在这种情况下,这两行并不相等,因为

#if LINUX_VERSION_CODE == KERNEL_VERSION(3,12,49) && KERNEL_PATCH_LEVEL == 11
Run Code Online (Sandbox Code Playgroud)

无论第一个测试的结果是什么,都会评估这两个部分,因此预处理器在遇到 时会偶然发现语法错误&& == 11

但如果LINUX_VERSION_CODE == KERNEL_VERSION(3,12,49)为假,则使用以下结构:

#if LINUX_VERSION_CODE == KERNEL_VERSION(3,12,49) 
#if KERNEL_PATCH_LEVEL == 11
  ...
#endif //KERNEL_PATCH_LEVEL == 11
#endif 
Run Code Online (Sandbox Code Playgroud)

您没有输入第一个#if,因此内部#if(由于 value 是错误的#if == 11)属于预处理器跳过的块,这说明没有错误。

请注意,如果KERNEL_PATCH_LEVEL未定义,#if则将其视为0,不会触发任何错误。

你可以用这个来防止错误定义KERNEL_PATCH_LEVEL(参见测试空宏定义,我现在添加了一个更好的答案)

#if (KERNEL_PATCH_LEVEL + 0) == 0
#undef KERNEL_PATCH_LEVEL
#define KERNEL_PATCH_LEVEL 0
#endif
Run Code Online (Sandbox Code Playgroud)

因此,如果宏定义为空(或为 0),则取消定义它并将其定义为一个0值。您甚至可以检测(请参阅上面链接中的我的答案以了解其工作原理)它是否为空,而不是像0这样:

#if (0-KERNEL_PATCH_LEVEL-1)==1 && (KERNEL_PATCH_LEVEL+0)!=-2
#error "KERNEL_PATCH_LEVEL defined empty"
#endif
Run Code Online (Sandbox Code Playgroud)