2014-10-11 128 views
0

我已经在头文件中使用预处理宏在我的代码中添加了一堆“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$ 
+3

无关,但从技术上说,并且通过规范,具有两个前导下划线的符号保留供编译器和标准库使用。 – 2014-10-11 23:13:38

+1

为了记录目的使用这种宏的一个小技巧: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

+0

@datenwolf现在我在我的可变参数宏中使用了## __ VA_ARGS__(即__VA_ARGS__前面有两个#符号),它似乎与-std = gnu99一起工作。你预见到这个组合有任何问题吗? (目前我只是一个C学生,并且还没有碰到交叉编译器问题。) – iceman 2014-10-12 00:07:49

回答

2

的proeprocessor,就像C编译器,扫描文件,从顶部到底部。这意味着在使用之前,宏必须定义为

所以要解决您的问题,请在之前加#define

#include <stdio.h> 

#define KRYPTONITE 

#include "test.h" 

int main (int argc, char *argv[]) 
{ 
    printf("\nSuperman, are you here?\n\n"); 
    superman("I'm here"); // Doesn't print 
    return 0; 
} 
+0

添加了代码示例来说明。 – 2014-10-11 23:16:26