您有一些误解:首先是“调用”宏的概念。这是不可能的,即使一个宏看起来像一个函数,它也不是一个函数,而且宏实际上并没有被编译器处理。相反,宏是由preprocessor 处理的单独语言的一部分,它获取源文件并对其进行修改以生成编译器看到的translation unit。 (有关“编译”不同阶段的更多信息,请参见例如this reference。)
预处理器基本上通过在输入源文件中执行搜索替换来完成此操作:当它看到宏“调用”时,它只是将其替换为宏的“主体”。当它看到#include 指令时,它会预处理文件,然后将内容放在指令的位置。
因此,在您的代码中,当预处理器看到宏 MESSAGE 时,它实际上会被 "this is message!" 替换。实际的编译器根本看不到MESSAGE,它只看到字符串文字。
另一个误解是你如何使用#include 指令。您不应该使用它来包含 source 文件。相反,您需要单独编译源文件(这会创建目标文件),然后将生成的目标文件与生成最终可执行文件所需的任何库链接。
要解决所有源文件都可以使用宏(和其他声明)的问题,您可以使用头文件。这些类似于源文件,但仅包含 声明 和宏。然后,您将头文件包含在两个源文件中,两个源文件都会知道头文件中可用的声明和宏。
所以在您的情况下,您应该有 三个 文件:主源文件、包含函数的源文件以及包含宏和函数声明的头文件(也称为原型) .类似的东西
头文件,例如header.h:
// First an include guard (see e.g. https://en.wikipedia.org/wiki/Include_guard)
#ifndef HEADER_H
#define HEADER_H
// Define the macro, if it needs to be used by all source files
// including this header file
#define MESSAGE "this is message!"
// Declare a function prototype so it can be used from other
// source files
void helloworld();
#endif
主要源文件,例如main.c:
// Include a system header file, to be able to use the `printf` function
#include <stdio.h>
// Include the header file containing common macros and declarations
#include "header.h"
int main(void)
{
// Use the macro
printf("From main, MESSAGE = %s\n", MESSAGE);
// Call the function from the other file
helloworld();
}
另一个文件,例如hello.c:
// Include a system header file, to be able to use the `printf` function
#include <stdio.h>
// Include the header file containing common macros and declarations
#include "header.h"
void helloworld(void)
{
printf("Hello world!\n");
printf("From helloworld, MESSAGE = %s\n", MESSAGE);
}
现在,如果您使用像 gcc 或 clang 这样的命令行编译器,那么您可以简单地构建它,例如:
$ gcc -Wall main.c hello.c -o myhello
该命令将获取两个源文件 main.c 和 hello.c 并在它们上运行预处理器和编译器以生成(临时)目标文件。然后将这些目标文件与标准 C 库链接在一起以形成程序 myhello(这就是选项 -o 所做的,命名输出文件)。
然后你可以运行myhello:
$ ./我的你好
从主要,MESSAGE = 这是消息!
你好世界!
来自 helloworld,MESSAGE = 这是消息!