前言
学习AFNetWoring源码的时候,在AFN的h借接口文件又看到了这几个宏定义,学习记录一下。
作用
#ifndef, #define, 和 #endif
是C/CPP的预处理指令,常常用来条件编译和防止头文件重复包含。
简介
#ifndef
它是if not define
的简写,是宏定义的一种,确切的说是预处理功能(宏定义、文件包含、条件编译)三种中的一种——条件编译。
使用#ifndef可以避免以下错误:如果在.h文件中定义了全局变量,一个C文件包含了.h文件多次,如果不加#ifndef宏定义,会出现变量重复定义的错误;如果加了#ifndef则不会出现这种错误。
- #ifndef:如果未定义)用于判断指定的标识符是否已经被定义。如果该标识符未定义,则执行下面的代码块,否则跳过。
- #define: 用于定义指定的标识符,通常用于定义宏。在条件编译中,一般用来定义一个标识符,以便在后面的代码中进行条件判断。
- #endif :用于结束条件编译的代码块。
通常语法如下
#ifndef IDENTIFIER
#define IDENTIFIER
// 在这里放置需要执行的代码
#endif
其中,IDENTIFIER
是你自己定义的标识符名称,可以是任意合法的标识符。
这种结构的作用是为了防止头文件的重复包含。通过定义一个唯一的标识符,当该头文件第一次被包含时,IDENTIFIER 未定义,预处理器会执行 #define
下的代码块,标识该头文件已经被包含。当同一个头文件再次被包含时,由于 IDENTIFIER 已经被定义,预处理器会跳过 #define 下的代码块,从而避免了重复包含。
这种写法在头文件中很常见,以确保头文件的内容只会被编译一次,防止重复定义和冲突。
例子
以开头的代码为例
#ifndef _AFNETWORKING_
#define _AFNETWORKING_
#import "AFURLRequestSerialization.h"
#import "AFURLResponseSerialization.h"
#import "AFSecurityPolicy.h"
#if !TARGET_OS_WATCH
#import "AFNetworkReachabilityManager.h"
#endif
#import "AFURLSessionManager.h"
#import "AFHTTPSessionManager.h"
#endif /* _AFNETWORKING_ */
这段代码的是OC的预编译指令,用于编译时对于代码进行条件判断和控制
- #ifndef:预处理指令,用于判断一个标识符是否已经被定义过。如果标识符没有被定义过,则编译下面的代码块,否则忽略下面的代码块。
- #define:预处理指令,用于定义一个标识符。在这个例子中,AFNETWORKING 就是被定义的标识符。
- #endif:预处理指令,用于结束一个条件编译块。
这段代码的作用是:当AFNETWORKING
这个标识符没有被定义时,编译下面的代码块,并且将AFNETWORKING
定义为已经被定义。这样可以避免头文件的重复引用和编译错误。
分解
#ifndef _AFNETWORKING_
#define _AFNETWORKING_
这里定义了一个标识符 _AFNETWORKING_
,如果该标识符未定义(即未被之前的代码定义过),则执行下面的代码块,否则跳过。
#import "AFURLRequestSerialization.h"
#import "AFURLResponseSerialization.h"
#import "AFSecurityPolicy.h"
这里通过#import
指令引入了一些其他的头文件,这些头文件可能包含了一些类或函数的声明。
#if !TARGET_OS_WATCH
#import "AFNetworkReachabilityManager.h"
#endif
这段代码使用了条件编译,判断是否为目标平台是不是watchOS,如果不是watchOS,则引入 "AFNetworkReachabilityManager.h"
头文件。
#import "AFURLSessionManager.h"
#import "AFHTTPSessionManager.h"
这里又引入了两个头文件 "AFURLSessionManager.h"
和 "AFHTTPSessionManager.h"
。
最后,代码块的结束部分是 #endif
,用于结束条件编译的代码块。
整个结构的目的是为了确保头文件的内容只会被编译一次,避免了重复定义和冲突。