我经常在 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
语句中使用时未定义。
答案 0 :(得分:10)
据我所知,如果在
#if
语句中使用宏未定义,则没有预处理器选项可以抛出错误/警告。
它不能是错误,因为C标准指定行为是合法的。从ISO C99标准的第6.10.1 / 3节开始:
由于宏扩展和
defined
一元的所有替换后 已执行运算符,所有剩余的标识符将替换为pp-number0
...
正如Jim Balter在下面的评论中指出的那样,一些编译器(例如gcc)可以发出关于它的警告。但是,由于将0
替换为未识别的预处理器令牌的行为是合法的(并且在许多情况下是可取的),我希望在实践中启用此类警告会产生大量噪音。
没有办法完全按照自己的意愿行事。如果要在未定义宏的情况下生成编译失败,则必须明确执行
#if !defined DEBUG_PRINT
#error DEBUG_PRINT is not defined.
#endif
为每个关心的源文件。或者,您可以将宏转换为类似函数的宏,并避免使用#if
。例如,您可以定义一个DEBUG_PRINT
宏,该宏扩展为调试版本的printf
调用,但对于非调试版本,则扩展为空。任何忽略包含定义宏的头的文件都将无法编译。
编辑:
关于可取性,我已经多次看到代码使用的地方:
#if ENABLE_SOME_CODE
...
#endif
而不是:
#ifdef ENABLE_SOME_CODE
...
#endif
以便#define ENABLE_SOME_CODE 0
禁用代码而不是启用它。
答案 1 :(得分:9)
这可能不适用于一般情况(我认为没有针对您所要求的通用解决方案),但对于您的具体示例,您可以考虑更改此代码序列:
#if(DEBUG_PRINT == 1)
printf("%s", "Testing");
#endif
为:
if (DEBUG_PRINT == 1) {
printf("%s", "Testing");
}
如果未定义DEBUG_PRINT
或者将其定义为无法与1
进行比较的内容,则不会再编译并且无法编译。
答案 2 :(得分:8)
不要直接在源文件中使用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建议使用普通if
而不是#if
(是的,优化器不会生成代码假常数测试)。
编辑: 只要您没有看起来像宏参数的逗号,就可以将上面的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++;)
答案 3 :(得分:2)
是的,您可以同时查看两者:
#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)
,也不会打印任何内容
答案 4 :(得分:0)
只需创建一个执行实际打印的宏DEBUG_PRINT:
#define DEBUG_PRINT(n, str) \
\
if(n == 1) \
{ \
printf("%s", str); \
} \
else if(n == 2) \
{ \
do_something_else(); \
} \
\
#endif
#include <stdio.h>
int main()
{
DEBUG_PRINT(1, "testing");
}
如果未定义宏,则会出现编译器错误,因为无法识别该符号。
答案 5 :(得分:0)
#if 0 // 0/1
#define DEBUG_PRINT printf("%s", "Testing")
#else
#define DEBUG_PRINT printf("%s")
#endif
因此,当“if 0”时它什么也不做,当“if 1”时它将执行定义的宏。