#define多个文件中的范围

时间:2012-01-02 11:27:33

标签: c scope c-preprocessor

我有一个像这样的主文件:

main_a.c:

#define MAIN_A

#include <stdio.h>
#include "shared.h"

extern int i;
int main() {
  printf("i is: %d\n", i);
  return 0;
}

我想在shared.h中使用define,如下所示:

shared.h

#if defined(MAIN_A)
# define A
#endif

所以我可以根据主文件是否存在来声明变量,如下所示:

shared.c

#include "shared.h"

#if defined(A)
int i = 1;
#else
int i = 0;
#endif

我使用makefile构建它,如下所示:

生成文件:

all : a
    ./a

a : main_a.o shared.o
    gcc -o $@ $^

%.o : %.c
    gcc -c $<

然而这打印

i is: 0

现在我的问题是:为什么编译共享模块时定义似乎丢失了?我知道主模块是先编译的,所以定义应该在编译shared.c时解决。

我怀疑的是,预处理器可能会在每个模块构建开始时运行,而不仅仅是在项目开始时运行。如果这是正确的,有一种方法可以一次编译多个模块,以便在我上面尝试时使用预处理器吗?

5 个答案:

答案 0 :(得分:12)

预编译器在编译之前为每个文件运行,即一次用于main_a.c,然后再次独立用于shared.c。编译shared.c时,MAIN_A未定义。

预处理器不能以您尝试的方式使用,即在编译单元之间记住状态。

您可以使用Makefile中的MAIN_A编译器选项定义名称(例如-D),并使用预处理器以与现在相同的方式测试此名称。这样定义发生在项目级别(在Makefile中)而不是在编译单元级别(在.c文件中)。

答案 1 :(得分:1)

让我在这里完成预处理器的工作并扩展所有宏。在main.c中定义了MAIN_A,因此定义了A。没有任何内容取决于A中的main.ci是外部的。

shared.c中,MAIN_A因此A未定义,i为0。

简而言之,预处理器无法在编译单元之间传输信息。这是一种很好的做法,因为否则程序会很快变得不可读,当一个单元发生变化时,你必须重新编译所有编译单元(因为符号可能已经改变)。通过在i中明确设置main来解决问题:

 int main() {
     i = 1;
 }

它更冗长,但读者也更清楚。如果要封装,请定义函数InitializeShared。如果您真的想将一些代码编译为单个编译单元,请将其中一个文件作为头文件,将#include作为另一个文件。

答案 2 :(得分:0)

是的,你是对的,它们是完全独立的编译单元。

MAIN_A仅在main_a.c中定义

我想到的一个想法是将文件合在一起制作一个编译单元?

答案 3 :(得分:0)

全球定义A

gcc main_a.c shared.c -DA

答案 4 :(得分:-1)

定义几乎与任何变量相同的工作。如果要跨模块共享变量,请将其放在标题中。 #defines也一样。

然而,使用#ifdef很奇怪,因为你总是会有main.c.您不希望每次编译时都更改代码。相反,使用Adam Zalcman描述的方法