我已经在头文件中使用预处理宏在我的代码中添加了一堆“debug(x)”语句。我还实现了一个切换(通过头文件中的#ifdef/#else结构),可以让我关闭调试语句。我无法使此切换开始工作,并希望有人能够找出原因。C:对预处理宏的困惑
而不是重新发布实际的代码(这是很长的),我包括一个说明性的例子(它编译)。
这是我们的.h文件。它由一个名为“超人”的函数组成。当且仅当KRYPTONITE没有在我们的.c文件中定义时,该语句应该打印。
test.h:
#ifndef __test_h__
#define __test_h__
#ifdef KRYPTONITE
#define superman(...)
#else
#define superman(xs) printf("%s\n\n",xs)
#endif
#endif
正如你可以在下面的情况看,加入了“的#define KRYPTONITE 1”的声明对我们的.c文件的开头不切换掉了“超人”功能(下面的案例2)。但是,如果我们通过编译指令中的一个标志定义KRYPTONITE,则我们确实成功切换(情况3)。
为了通过.c文件中的“#define”语句关闭“超人”功能,还需要做些什么?例1:KRYPTONITE没有在.c文件中定义(它被注释掉了)。正如预期的那样,该声明将被打印(.c文件和输出低于。)
test1.c:
#include <stdio.h>
#include "test.h"
//#define KRYPTONITE
int main (int argc, char *argv[])
{
printf("\nSuperman, are you here?\n\n");
superman("I'm here");
return 0;
}
输出:
[email protected]:~/SO$ gcc test1.c -o test1
[email protected]:~/SO$ ./test1
Superman, are you here?
I'm here
[email protected]:~/SO$
情况2:KRYPTONITE是在我们的.c文件定义但声明打印。
test2.c中:
#include <stdio.h>
#include "test.h"
#define KRYPTONITE
int main (int argc, char *argv[])
{
printf("\nSuperman, are you here?\n\n");
superman("I'm here");
return 0;
}
输出:
[email protected]:~/SO$ gcc test2.c -o test2
[email protected]:~/SO$ ./test2
Superman, are you here?
I'm here
[email protected]:~/SO$
案例3:KRYPTONITE不在我们的.c文件中定义的,而是通过一个标志编译时,我们把它定义。在这种情况下,超人功能被成功切换。
输出:
[email protected]:~/SO$ gcc -DKRYPTONITE test1.c -o test3
[email protected]:~/SO$ ./test3
Superman, are you here?
[email protected]:~/SO$
无关,但从技术上说,并且通过规范,具有两个前导下划线的符号保留供编译器和标准库使用。 – 2014-10-11 23:13:38
为了记录目的使用这种宏的一个小技巧:C99预处理器支持可变宏,MSVC也有它们。方式略有差异,处理扩展中的尾随逗号。例如'#define log_printf(l,fmt,...)fprintf(stderr,“%c:”fmt,l,__VA_ARGS __)“。然而,对于GCC,这需要始终提供额外的参数,MSVC默默解决了这种情况。不过,GCC的扩展名可以写成'#__ VA_ARGS__'。 – datenwolf 2014-10-11 23:22:17
@datenwolf现在我在我的可变参数宏中使用了## __ VA_ARGS__(即__VA_ARGS__前面有两个#符号),它似乎与-std = gnu99一起工作。你预见到这个组合有任何问题吗? (目前我只是一个C学生,并且还没有碰到交叉编译器问题。) – iceman 2014-10-12 00:07:49