C中的范围和条件#define

时间:2018-09-28 12:20:55

标签: c c-preprocessor

我想使用本地.h文件定义在我的lib中使用的相同名称。我的库对此名称有一个默认值定义,但我想使用本地.h文件更改此默认值。但是,我有不想要的行为。我该怎么解决?

test.c

#include <stdio.h>
#include <string.h>
#include <stdint.h>

#include "conf.h"
#include "mylib.h"

int main ()
{
  printf("Value in main: %d\n", NAMEDEFINITION);
  fn();

  return 0;
}

conf.h

#define NAMEDEFINITION 42 

mylib.h

#include <stdio.h>
#include <string.h>
#include <stdint.h>

#ifndef NAMEDEFINITION
  #define NAMEDEFINITION 84 
#endif

void fn(); 

mylib.c

#include "mylib.h"

void fn()
{
  printf("Value in fn: %d\n", NAMEDEFINITION);
  return;
}

我的编译行和输出:

user@local:~/user/test/c$ gcc test.c mylib.c -o test
user@local:~/user/test/c$ ./test
Value in main: 42
Value in fn: 84

[编辑]

我希望在conf.h中定义NAMEDEFINITION为“ 42”,然后在两个main()调用中打印“ 42”。在conf.h中未定义时,它将是默认值“ 84”(在两个main()调用中打印“ 84”。

3 个答案:

答案 0 :(得分:4)

Value in main: 42

这样做的原因是,在test.c中您已经包含了conf.h,即使您包含了mylib.hNAMEDEFINITIONtest.c和{{1 }}的值为42。NAMEDEFINITION中的ifdef无效。

mylib.h

Value in fn: 84 中,您没有包括mylib.c。因此,conf.h行将为true,#ifndef NAMEDEFINITION的值为84。

如果您希望fn中的值也显示42,则需要在NAMEDEFINITIONconf.h中包含mylib.c

然后,如果将mylib.h中的行#define NAMEDEFINITION 42注释掉,则值84将被两次打印。

答案 1 :(得分:2)

我看到您可以通过以下三种方式进行操作:

1。将配置文件强制设置为库的一部分

mylib.h

#include <stdio.h>
#include <string.h>
#include <stdint.h>

#include "conf.h"
#ifndef NAMEDEFINITION
  #error NAMEDEFINITION hasn't beed defined! Please edit conf.h!
#endif

void fn(); 

2。使用编译选项定义NAMEDEFINITION

示例:

-D NAMEDEFINITION=42

使用这种方法,您根本不会使用conf.h文件。此方法的缺点是必须确保记住两个.c文件编译都包含此选项。

3。将conf.h包含在编译选项中

示例:

-include conf.h

这与方法2相似,但是您不必直接定义符号,而可以强制包含conf.h。


无论做什么,请确保您的头文件具有include guards。 (感谢@ChristianGibbons)

答案 2 :(得分:1)

解释很简单。

第一个示例(主要) 在conf.h中定义它。当包含mylib.h时,它已经被定义并且没有被重新定义。因此值为42

在第二个示例(fn)中,仅包含mylib.h,并且#ifndef条件为true。

宏在编译之前已展开,并且仅在一个编译单元中有效。