在C主体中包含头文件的机制
对于C开发的大型软件,我们首先在单独的头文件中声明所有自定义函数(例如,在C主体中包含头文件的机制,c,header-files,C,Header Files,对于C开发的大型软件,我们首先在单独的头文件中声明所有自定义函数(例如,myfun.h)。之后,一旦我们编写了使用myfun.h中列出的函数的代码(例如main.c),我们就必须#包括“myfun.h”。我想知道它是如何工作的,因为即使我在主体之前包含头文件中声明的函数名,代码也无法在main.c中看到函数的详细信息。我猜它会搜索函数库以获取函数详细信息……我说得对吗?当你说“它会搜索函数库以获取函数详细信息”时,你说的并不遥远,但这并不完全正确。函数声明,即函数原型仅包含编译器执行两件事所需的
myfun.h
)。之后,一旦我们编写了使用myfun.h
中列出的函数的代码(例如main.c
),我们就必须#包括“myfun.h”
。我想知道它是如何工作的,因为即使我在主体之前包含头文件中声明的函数名,代码也无法在main.c
中看到函数的详细信息。我猜它会搜索函数库以获取函数详细信息……我说得对吗?当你说“它会搜索函数库以获取函数详细信息”时,你说的并不遥远,但这并不完全正确。函数声明,即函数原型仅包含编译器执行两件事所需的足够信息:
- 首先,编译器将函数注册为一个已知标识符,这样它就知道你调用它时要做什么,而不是一个带括号的随机字母串(对于编译器来说,它们本质上是相同的,没有函数原型——一个错误)
- 其次,编译器使用函数原型检查代码的正确性。从这个意义上讲,正确性意味着函数调用将在算术和类型上与原型匹配。换句话说,函数调用
intsquare(inta,intb)代码>将有两个参数,都是整数
回到预处理器,需要注意两件事。首先,它在编译之前运行。这很重要。由于在预处理器执行任务时,程序并没有真正被“编译”,因此宏不是类型安全的。(插入Haskell关于C类型安全的笑话)这就是为什么你不应该或者不应该看到C++中的宏。在C中可以用宏实现的任何东西都可以通过代码> > const 和C++中的内联函数来完成,同时也增加了类型安全性的好处。 其次,预处理器几乎只是一个搜索和替换引擎。例如,在下面的代码中,由于预处理器
if
语句的计算结果为false,所以不会发生任何事情,因为我从未定义过任何内容。预处理器将删除此部分中的代码。请记住,由于编译器尚未认真运行,因此不会编译删除的代码。这一事实通常用于实现调试或登录调试构建的功能。在发布版本中,预处理器定义随后被操纵,这样就不包括调试代码
#include <stdio.h>
#include <stdlib.h>
int main()
{
#if TRUE
printf("Hello, World!");
#endif
return EXIT_SUCCESS;
}
预处理器的另一个重要用途是代码可移植性,例如:
#ifdef WIN32
// Do windows things
#elif
// Handle other OS
#endif
一个技巧是定义一个通用函数并将其设置为适当的依赖于操作系统的函数(请记住,没有括号的函数表示函数的地址,而不是实际的函数调用),如下所示:
// Not valid C89, possibly even C99
const int DEFAULT_BUFFER_SIZE = 128;
char user_input[DEFAULT_BUFFER_SIZE];
// Legal since the dawn of time
#define DEFAULT_BUFFER_SIZE 128
char user_input[DEFAULT_BUFFER_SIZE];
void RequestSomeKernelAction();
#ifdef WIN32
RequestSomeKernelAction = WindowsVersion;
#else
RequestSomeKernelAction = OtherOSFunction;
#endif
这就是说您在头文件中看到的代码遵循相同的规则。如果我有以下头文件:
#ifndef SRC_INCLUDES_TEST_H
#define SRC_INCLUDES_TEST_H
int square(int a);
#endif /** SRC_INCLUDES_TEST_H */
我有一个主.c文件:
#define SRC_INCLUDES_TEST_H
#include "test.h"
int main()
{
int n = square(4);
}
这个程序不会编译。main.c不知道square函数,因为虽然我包含了声明square
的头文件,但我的\define SRC\u INCLUDES\u TEST\u H
语句告诉预处理器将所有头文件内容复制到main,除了定义SRC\u INCLUDES\u TEST\u H
的块中的内容,也就是说,什么都没有
这些预处理器命令可以嵌套,并且有几个,我强烈建议您查找,如果只是出于历史或教学原因的话
我要说的最后一点是,虽然C预处理器有它的缺点,但它是右手中的一个强大工具,事实上,Bjarne Stroustroup编写的第一个C++编译器本质上只是一个预处理器。你想读函数/变量声明和定义……你知道链接是什么意思吗?如果你正在编写一个大型软件,你应该考虑学习——至少是灵感——一些与你的领域相似或雄心勃勃的源代码。你会发现其中很多,例如,在标题上声明了其他地方可用的内容。例如,
告诉编译器标准C中可用的函数等