如果我们在代码编写过程中,有一段代码弃之可惜,保留无用你会如何做呢?是直接删除还是大面积注释?当学习了解条件编译以后,就可以条件编译来“装b”的注释掉了。那么,让我们来看看什么是条件编译!
条件编译,顾名思义,就是有条件的进行编译。举个例子:
#include
#define DEBUG
int main()
{
int i = 0;
int arr[10] = { 0 };
for (i = 0; i < 10; i++)
{
arr[i] = i;
#ifdef DEBUG //如果定义了 DEBUG 就编译下面的代码
printf("%d\n", arr[i]);//为了观察数组是否赋值成功。
#endif //结束条件编译
}
return 0;
}
在上面的代码中,我们使用printf函数只是为了调试观察数组是否赋值成功,但是对整个程序的功能是多余的。此时我们就可以使用条件编译,当满足条件时编译该条语句,不满足条件时则不编译该条语句。
#ifdef DEBUG的意思就是如果定义了 DEBUG 就编译下面的代码。那么这个条件何时结束呢?就是直到遇到了#endif 就结束条件编译。
常见的条件编译指令:
1.比较直接简单的条件编译:
1.最简单的条件编译:
#if (常量表达式)
//...
#endif
//常量表达式由预处理器求值。
如:
#define __DEBUG__ 1
#if __DEBUG__
//..
#endif
注意:这里#if后面应该是常量表达式。
使用举例:
int main()
{
//3==5为假,所以不打印”哈哈“
#if 3==5
printf("哈哈\n");
#endif
//3是真,所以打印”呵呵“
#if 3
printf("呵呵\n");
#endif
return 0;
}
2.多个分支的条件编译:
2.多个分支的条件编译:
#if (常量表达式)
//...
#elif (常量表达式)
//...
#else
//...
#endif
使用举例:
int main()
{
//3==5为假,所以不打印”哈哈“
#if 3==5
printf("哈哈\n");
//5>2是真,所以打印”嘿嘿“
#elif 5>2
printf("嘿嘿\n");
//上一个elif是真,所以这里不打印“呵呵”
#else
printf("呵呵\n");
#endif
return 0;
}
可以看到,多个分支的条件编译#if … #elif … #else …的使用和if-else语句是很相似的。
3.根据是否被定义来判断:
3.判断是否被定义:
//如果定义了则编译的两种写法:
#if defined(symbol)
#ifdef symbol
//如果没定义则编译的两种写法:
#if !defined(symbol)
#ifndef symbol
使用举例
#define DEBUG 100
int main()
{
#ifdef DEBUG //如果定义了 DEBUG 就编译下面的代码
printf("定义了DEBUG\n");
#endif //结束条件编译
#ifndef TEST //如果没定义TEST,就编译下面的代码
printf("没定义TEST\n");
#endif //结束条件编译
return 0;
}
4.嵌套指令:
4.嵌套指令:
#if defined(OS_UNIX)
#ifdef OPTION1
unix_version_option1();
#endif
#ifdef OPTION2
unix_version_option2();
#endif
#elif defined(OS_MSDOS)
#ifdef OPTION2
msdos_version_option2();
#endif
#endif
目前作为初学者,我们可能用不到这些东西,但是了解了可以让我们能够阅读别人的代码。在以后编写复杂程序代码的时候,条件编译将会满足很多需求!
我们已经知道, #include 指令可以使另外一个文件被编译。就像它实际出现于 #include 指令的地方一样。 这种替换的方式很简单: 预处理器先删除这条指令,并用包含文件的内容替换。 这样一个源文件被包含10次,那就实际被编译10次。
#include "filename.h"
如果是我们自己创建的.h头文件需要被包含,就使用"“来包含。
使用”"包含时,当系统编译的时候,会先去我们项目的文件夹中寻找该头文件,如果找不到,就去库文件的目录下寻找。如果还找不到就报错。
#include
我们要包含库函数所在的头文件,需要用<>来包含。
使用<>包含时,当系统编译的时候,直接就去库文件目录寻找头文件了。
因此,对于库函数头文件,两种方式均可。但是还是用<>更好,寻找的效率更高。
对于本地头文件,就只能用""包含!
我们知道,包含头文件在编译时会将该头文件中的东西完整复制一遍。如果我们的程序多次调用同一个头文件,那么调用时也会多次调用,使得编译代码十分冗余,那么我们该如何防止这种情况呢?
1. #pragma once
在头文件开头加上这个预处理指令,它表示该头文件只会被引用一次,即使在多个文件中被包含。
2.条件编译
我们介绍了条件编译,那么如何利用条件编译来达到头文件只被包含一次的目的呢?
#ifndef __TEST_H__
#define __TEST_H__
//头文件的内容
#endif
在头文件中加入上述预处理指令,将头文件中的内容写在中间。
这是什么逻辑呢?
因为#ifndef __TEST_H__表示如果没有定义__TEST_H__这个东西才会执行下面的代码,当第一次包含该头文件时,TEST_H__确实没有被定义,于是执行该头文件中的所有代码。但是第一次执行后,因为下一句就是定义#define TEST_H,所以第一次执行该头文件中的代码后,下一次再用#ifndef判断时,因为第一次包含头文件时已经定义了__TEST_H,那么下面的代码就不会再执行了。
由此达到了只包含一次头文件的目的!