当你在编写一个头文件(例如 pid_controller.h
)时,你可能会在多个源文件中包含它,以便在这些源文件中使用该头文件定义的函数、类或其他声明。如果你在多个源文件中都包含了同一个头文件,那么当你将整个工程统一编译,希望链接成一个完整的可执行文件时,就会出现大量错误,因为每一个相同的头文件都会进行所谓的“重定义”,导致重复定义的错误。
但是如果加上了上面这三句代码,就不会出现重复定义的错误了:
#ifndef PID_CONTROLER_H
#define PID_CONTROLER_H
//在这里写pid_controler.h所需要的具体内容
#endif
作用:
- #ifndef:检查是否定义了宏PID_CONTROLER_H,如果未定义,那么从#define开始一句句的执行下面的代码块;如果已定义,说明之前已经包含过这个头文件,那么就跳过这个代码块,即直接跳到#endif后面,避免重复定义
- #define:定义了宏 PID_CONTROLER_H,这样在当前编译单元中就有了一个标记,表示这个头文件已经被包含过了
-
在#define和#ifndef之间,你可以放置头文件的内容,包括函数声明、类声明等
-
#endif:表示条件编译的结束
因此,当你在其他源文件中包含 pid_controller.h
时,预处理器会首先检查是否已经包含过该头文件。如果之前已经包含过,那么就不会再次包含,这样就避免了重复定义的问题。
注意1:
我们在使用define关键字时经常是这样的:
#define MAX_SIZE 100
MAX_SIZE
是一个宏名,它被定义成一个常量值 100,
这意味着,在后续的代码中,每当出现 MAX_SIZE
这个名字,预处理器会将其替换为 100;
但如果是这样的:
#define MAX_SIZE
当 #define
后面没有跟着一个具体的值时,它实际上是定义了一个宏,但它并没有给这个宏赋予一个特定的值。在这种情况下,它通常用于条件编译,起到一个开关的作用。就是我们介绍的【#ifndef + #define + #endif】所实现的作用;
注意2:
一般我们每个头文件要定义的宏是不能一样的,因此我们在定义的时候,通常使用头文件的名称作为宏,例如:
我的头文件名为pid_controler.h,所以这个头文件所使用的宏被命名为_PID_CONTROLER_H;