有没有办法检查宏是否已定义,并且它同时等于某个值

我经常使用类似对象的预处理器宏作为C代码中的布尔标志来打开和关闭代码段。

例如

#define DEBUG_PRINT 1 

然后像使用它一样

 #if(DEBUG_PRINT == 1) printf("%s", "Testing"); #endif 

但是,如果包含#define的头文件忘记包含在源代码中,则会出现问题。 由于未声明宏,因此预处理器将其视为等于0,并且#if语句永远不会运行。

当忘记包含头文件时,可能发生非预期的,不守规矩的行为。

理想情况下,我希望能够检查宏是否已定义,并在一行中检查它是否等于某个值。 如果未定义,则预处理器会抛出错误(或警告)。

我正在寻找以下内容:

 #if-def-and-true-else-throw-error(DEBUG_PRINT) ... #endif 

它就像#ifdef#if的组合,如果它不存在,则使用#error

我已经探索了一些途径,但是,预处理器指令不能在#define块中使用,据我所知,如果在内部使用宏时没有定义宏,则没有预处理器选项来抛出错误/警告#if语句。

这可能不适用于一般情况(我认为没有针对您要求的通用解决方案),但是对于您的具体示例,您可以考虑更改此代码序列:

 #if(DEBUG_PRINT == 1) printf("%s", "Testing"); #endif 

至:

 if (DEBUG_PRINT == 1) { printf("%s", "Testing"); } 

如果没有定义DEBUG_PRINT或者它被定义为无法与1比较的东西,它就不再冗长并且将无法编译。

据我所知,如果在#if语句中使用宏时未定义宏,则没有预处理器选项可以抛出错误/警告。

它不能是错误,因为C标准指定行为是合法的。 从ISO C99标准的第6.10.1 / 3节开始:

在完成由于宏扩展和已defined一元运算符而导致的所有替换之后,所有剩余的标识符将替换为pp-number 0 ….

正如Jim Balter在下面的评论中指出的那样,一些编译器(例如gcc)可以发出关于它的警告。 但是,由于将0替换为未识别的预处理器令牌的行为是合法的(并且在许多情况下是可取的),我希望在实践中启用此类警告会产生大量噪声。

没有办法完全按照你的意愿去做。 如果要在未定义宏的情况下生成编译失败,则必须明确地执行此操作

 #if !defined DEBUG_PRINT #error DEBUG_PRINT is not defined. #endif 

对于每个关心的源文件。 或者,您可以将宏转换为类似函数的宏,并避免使用#if 。 例如,您可以定义一个DEBUG_PRINT宏,该宏扩展为用于调试版本的printf调用,但对于非调试版本,则扩展为无。 任何忽略包含定义宏的头的文件都将无法编译。

而不是直接在源文件中使用DEBUG_PRINT,将其放在头文件中:

 #if !defined(DEBUG_PRINT) #error DEBUG_PRINT is not defined #endif #if DEBUG_PRINT #define PrintDebug([args]) [definition] #else #define PrintDebug #endif 

任何使用PrintDebug但不包含头文件的源文件都将无法编译。

如果您需要其他代码而不是基于DEBUG_PRINT编译的PrintDebug,请考虑使用Michael Burr建议使用plain而不是#if (是的,优化器不会在false常量测试中生成代码)。

编辑:只要你没有看起来像宏参数的逗号,你可以概括上面的PrintDebug包含或排除任意代码:

 #if !defined(IF_DEBUG) #error IF_DEBUG is not defined #endif #if IF_DEBUG #define IfDebug(code) code #else #define IfDebug(code) #endif 

那你可以写点东西

 IfDebug(int count1;) // IfDebug(int count1, count2;) won't work IfDebug(int count2;) ... IfDebug(count1++; count2++;) 

是的你可以检查两个:

 #if defined DEBUG && DEBUG == 1 # define D(...) printf(__VA_ARGS__) #else # define D(...) #endif 

在这个例子中,即使#define DEBUG 0但它不等于1,因此不会打印任何内容。

你甚至可以这样做:

 #if defined DEBUG && DEBUG # define D(...) printf(__VA_ARGS__) #else # define D(...) #endif 

如果您#define DEBUG 0然后D(1,2,3)也没有打印任何内容

DOC

只需创建一个执行实际打印的宏DEBUG_PRINT:

 #define DEBUG_PRINT(n, str) \ \ if(n == 1) \ { \ printf("%s", str); \ } \ else if(n == 2) \ { \ do_something_else(); \ } \ \ #endif #include  int main() { DEBUG_PRINT(1, "testing"); } 

如果未定义宏,则会出现编译器错误,因为无法识别该符号。

 #if 0 // 0/1 #define DEBUG_PRINT printf("%s", "Testing") #else #define DEBUG_PRINT printf("%s") #endif 

因此,当“if 0”时它什么都不做,当“if 1”时它将执行定义的宏。