头文件中的ifndef/define/endif有什么作用?
条件编译
#define ABCD 2
#include <iostream>
int main()
{
#ifdef ABCD
std::cout << "1: yes\n";
#else
std::cout << "1: no\n";
#endif
#ifndef ABCD
std::cout << "2: no1\n";
#elif ABCD == 2
std::cout << "2: yes\n";
#else
std::cout << "2: no2\n";
#endif
#if !defined(DCBA) && (ABCD < 2*4-3)
std::cout << "3: yes\n";
#endif
// 注意若编译器不支持 C++23 的 #elifdef/#elifndef 指令则会选择“不期待”块(见后述)。
#ifdef CPU
std::cout << "4: no1\n";
#elifdef GPU
std::cout << "4: no2\n";
#elifndef RAM
std::cout << "4: yes\n"; // 期待的块
#else
std::cout << "4: no!\n"; // 由于跳过未知的指令不期待地选择此块
// 并直接从 "#ifdef CPU" “跳”到此 "#else" 块
#endif
// 为修复此问题,我们可以条件性地仅若支持 C++23 指令 #elifdef/#elifndef
// 才定义 ELIFDEF_SUPPORTED 宏。
#if 0
#elifndef UNDEFINED_MACRO
#define ELIFDEF_SUPPORTED
#else
#endif
#ifdef ELIFDEF_SUPPORTED
#ifdef CPU
std::cout << "4: no1\n";
#elifdef GPU
std::cout << "4: no2\n";
#elifndef RAM
std::cout << "4: yes\n"; // 期待的块
#else
std::cout << "4: no3\n";
#endif
#else // 不支持 #elifdef 时使用累赘的旧 `#elif defined`
#ifdef CPU
std::cout << "4: no1\n";
#elif defined GPU
std::cout << "4: no2\n";
#elif !defined RAM
std::cout << "4: yes\n"; // 期待的块
#else
std::cout << "4: no3\n";
#endif
#endif
}
ifndef __XXX_H__ //意思是 "if not define __XXX_H__" 也就是没包含XXX.h
define __XXX_H__ //就定义__XXX_H__
... //此处放头文件中本来应该写的代码
endif //否则不需要定义
若未定义XXX.h则这里就定义XXX.h,然后运行里面的内容,若下次还走到了这个文件,则进行#ifndef的判断,则#ifndef与#endif之间的内容不会再次被载入
但是,必须记住的是预处理器仍将整个头文件读入,即使这个头文件所有内容将被忽略。由于这种处理将减慢编译速度,所以如果可能,应该避免出现多重包含。
补充:
通过使用#ifndef/define/endif,可以确保头文件只被包含一次,避免重复定义和无限循环编译的问题。
下面是一个具体的解决方案示例:
#ifndef _A_H_
#define _A_H_
// 头文件a.h的代码
#endif
#ifndef _B_H_
#define _B_H_
// 头文件b.h的代码
#endif
#include "a.h"
#include "b.h"
// test.cpp的代码
在预处理阶段,头文件a.h中的#ifndef指令会检查宏_A_H_是否已定义,如果未定义则继续执行下一行的#define指令,将宏_A_H_定义为真。此时头文件a.h中的代码会被执行。当编译器处理到头文件b.h时,由于宏_A_H_已经定义为真,ifndef块的代码将被跳过,避免了重复包含的问题。
需要注意的是,虽然预处理器仍会读取整个头文件的内容,但在#ifndef/define/endif的作用下,不会再次执行已被定义的代码块。因此,应该避免多次包含相同的代码块,以提高编译速度。
总结来说,使用#ifndef/define/endif可以确保头文件在编译过程中只被包含一次,避免了重复定义和无限循环编译的问题。编程时应该为每个头文件的开头和结尾都添加这些指令。
主要是避免头文件被重复包含。
比如说 my.h 头文件包含了 stdio.h
主程序同时包含了 stdio.h 和 my.h
那么如果stdio.h没有 ifndef ... ,那么其中的函数,就会被包含2次,相当于一个源代码里重复写了2个相同的代码,就会出错。