gcc 跨头文件重定义宏

czq61nw1  于 2023-02-23  发布在  其他
关注(0)|答案(1)|浏览(248)

我正在尝试(重新)定义我已设置的配置宏。下面是我想做的一个示例:

/* inc/foo.h */
#ifndef FOO_H
#define FOO_H

#include <stdio.h>

#ifndef FOO_CONF_MACRO
    #define FOO_CONF_MACRO 0
#endif

void foo(void);

#endif
/* src/foo.c */
#include "foo.h"

void foo(void)
{
    printf("%d\n", FOO_CONF_MACRO);
}
/* inc/bar.h */
#ifndef BAR_H
#define BAR_H

#include <stdio.h>

#define FOO_CONF_MACRO 3

#include "foo.h"

void bar(void);

#endif
/* src/bar.c */
#include "bar.h"

void bar(void)
{
    printf("Bar!\n");
}
/* app/main.c */
#include "bar.h"

#ifndef FOO_CONF_MACRO
    #undef FOO_CONF_MACRO
#endif
#define FOO_CONF_MACRO 18

#include "foo.h"

int main()
{
    foo();
    bar();
    return 0;
}

我希望编译所有文件并运行main.c后得到以下输出:

18
Bar!

然而,我实际观察到的是:

0
Bar!

或者,如果我没有在main.c中重新定义宏,我会期望:

3
Bar!

我发现this question非常相似。This answer特别让人觉得这取决于文件编译和链接的顺序。我同意OP的观点,尽管我已经多次看到这个构造在你自己编译的代码中实现配置宏。那么这真的取决于编译和链接的顺序吗?如果是的话,获得所需输出的正确顺序是什么?
目前,我在makefile中有以下代码:

### app/Makefile

INCLUDES = $(wildcard ../inc/*.h) #/**/

CFLAGS := -O2 -Wall -Wextra -std=gnu99 -I. -I../inc

### build targets
all: main

### modules
## submodules
obj:
    mkdir -p obj

obj/%.o: ../src/%.c $(INCLUDES) | obj
    gcc -c $(CFLAGS)

## main program
obj/main.o main.c $(INCLUDES) | obj
    gcc -c $(CFLAGS) $< -o $@

main: obj/main.o obj/bar.o obj/foo.o
    gcc $< obj/bar.o obj/foo.o -o $@

当我观察make的输出时,似乎先生成了main.o,然后是bar.o,最后是foo.o

e37o9pze

e37o9pze1#

源文件(foo.cbar.cmain.c)连同它们包含的 * 头文件 * 是三个独立的翻译单元,彼此没有任何联系。头文件与任何名称相似的源文件实际上是无关的。
如果您直接在源文件中更改一个翻译单元中的宏,那么其他翻译单元将不会知道它。
如果您更改了头文件中的宏,则只有包含头文件的翻译单元会知道它。
因为foo.c只包含foo.h,所以它只知道头文件中的宏。

相关问题