C++ #if #endif #define #ifdef #ifndef #if defined #if !defined详解
先了解一下 预处理命令:
在编译之前进行得处理,C语言得预处理主要有三个方面得内容:1.宏定义;2.文件包含;3.条件编译。预处理命令是以“#”符号开头的。
常见符号意义
#if //编译预处理中的条件命令,相当于C++中的if语句
#define //定义一个预处理宏
#undef //取消宏定义
#ifdef //判断某个宏是否被定义
#ifndef //判断某个宏是否未被定义,与#ifdef相反
#elif //当#if, #ifdef, #ifndef或前面的#elif条件不满足时,执行当前#elif之后的语句,相当于C++中的else-if
#else //与#if, #ifdef, #ifndef对应, 当这些条件都不满足时,执行#else之后的语句,相当于C++中的else
#endif //#if, #ifdef, #ifndef这些条件命令的结束标志,成对使用
defined //与#if, #elif配合使用,判断某个宏是否被定义
1、宏定义
可以对类型重命名,例如:
#define PI 3.141592654
宏可以带参数(也就是宏函数),#define 标识符(x1,x2…) 替换列表,注意标识符和(之间不能有空格,例如:
#define DeletePtrArr(p) if ((p)!=NULL) { delete[] (p);(p)=NULL;}
#define DeletePtr(p) {if(NULL!=p){delete p; p = NULL;}}
2、文件包含
#include "file"
#include <file>
使用双引号,系统首先到当前目录下查找被包含的文件,如果没找到,再到系统指定的"包含文件目录"(由用户在配置环境时设置)去找;而使用尖括号时,系统会直接到系统指定的"包含文件目录"去查找。通常使用双引号比较保险。
3、条件编译
常量表达式:
#define CONDITION
#if CONDITION
Printf(“Value of i:%d\n”, i);
#endif
#if 常量表达式,常量表达式为0时,预处理器会删除#if 和#endif中间的代码,并且#if 会把没有定义过的标准符视做为0,如果没有定义CONDITION, 则测试#if CONDITION会失败,但#if !CONDITION会成功,即如果常量表达式为一个没有定义的宏,它的值会被视作0。
取消已经定义的宏:
#if defined VALUE //检验VALUE是否被定义
#undef VALUE //如果已经被定义,解除定义
#define VALUE 77 //重新定义VALUE为77
#endif
检验是否被定义,还可以写成:
#ifndef VALUE //如果VALUE没有被定义
#define VALUE 77 //定义VALUE 为77
#endif
防止重复inclue:
方式1:
#if !defined __MYHEADER_H__
#define __MYHEADER_H__
#endif
方式2:
#ifndef __MYHEADER_H__
#define __MYHEADER_H__
#endif
方式3:(#pragma once)
#pragma once
#ifndef的方式依赖于宏名字不能冲突,这不光可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件不会被不小心同时包含。当然缺点就是如果不同头文件的宏名不小心“撞车”,可能就会导致头文件明明存在,编译器却硬说找不到声明的状况
#pragma once则由编译器提供保证:同一个文件不会被包含多次。注意这里所说的“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。带来的好处是,你不必再费劲想个宏名了,当然也就不会出现宏名碰撞引发的奇怪问题。对应的缺点就是如果某个头文件有多份拷贝,本方法不能保证他们不被重复包含。当然,相比宏名碰撞引发的“找不到声明”的问题,重复包含更容易被发现并修正。