程序预处理:全解版-1
https://developer.aliyun.com/article/1515706
三、#undef
用于移除#define定义的宏;我们来看这样的一个例子:
我们在上面引用define定义MAX 100 ,然后打印MAX,发现MAX可用,但是在接下来的一行使用了#undef MAX后,后面再去打印就显示语法错误----未定义标识符,可见在这个地方定义的MAX已经被移除了。
四、命令行定义
许多 C 的编译器提供了一种能力,允许在命令行中定义符号。用于启动编译过程。
例如:当我们根据同一个源文件要编译出一个程序的不同版本的时候,这个特性有点用处。(假定某个程序中声明了一个某个长度的数组,如果机器内存有限,我们需要一个很小的数组,但是另外一个机器内存大些,我们需要一个数组能够大些。)
举个例子:
#include <stdio.h> int main() { int arr [size]; int i = 0; for(i = 0; i< size i ++) arr[i] = i; for(i = 0; i< size; i ++) printf("%d " ,arr[i]); printf("\n" ); return 0; }
在编译的时候根据不同的需求,来命令size的大小,以确保程序在不同运行环境下的稳定性。
五、条件编译(选择性编译)
在编译的时候我们可以进行选择性编译,使用一下条件编译指令
1、单分支
#if 常量表达式
// .....
#endif
// .....
如:
#define __DEBUG__ 1
#if __DEBUG__
//..
#endif
2、多分支
#if 常量表达式
//...
#elif 常量表达式
//...
#else
//...
#endif
3.判断是否被定义
#if defined(symbol)
#ifdef symbol
#if !defined(symbol)
#ifndef symbol
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
单分支语句举例 运行结果为 0 1 2 3 4 5 6 7 8 9
#include <stdio.h> #define __DEBUG__ int main() { int i = 0; int arr[10] = {0}; for(i=0; i<10; i++) { arr[i] = i; #ifdef __DEBUG__ //判断条件,如果表达式结果为1则参与编译 printf("%d\n", arr[i]); #endif } return 0; }
看上面这个例子,如果__DEBUG__被定义,则编译执行printf语句,否则不编译
多分支举例 运行结果为 3;
#include<stdio.h> #include<stdlib.h> #define MAX 100 int main() { #if 1>2 printf("1"); #elif 2>3 printf("2"); #elif 4>3 printf("3"); #endif system("pause"); return 0; }
判断是否被定义: 结果为MAX has been defined
#include<stdio.h> #include<stdlib.h> #define MAX 100 int main() { #if defined(MAX) printf("MAX has been defined\n"); #endif #if defined(min) //仅仅只看你是否定义,不会显示未定义标识符 printf("???"); #endif system("pause"); return 0; }
(也可以将#if defined (MAX)改为
#ifdef MAX 这两者是等价的)
此外,#ifndef MAX则等价于 #if !defined(MAX)
加了一个n和!,意思就变为了:如果MAX没定义就真,执行语句就参与编译
这里的嵌套使用和我们c语言中的if else if语句用法差不多,这里不再赘述。
六、头文件包含
我们知道,工程里面的源文件通过编译器转化为目标文件后,通过链接器和链接库 链接形成可执行程序。
#include 指令可以使另外一个文件被编译。就像它实际出现于 #include 指令的地方一样
这种替换的方式很简单:
- 预处理器先删除这条指令,并用包含文件的内容替换。
- 这样一个源文件被包含10次,那就实际被编译10次。
1、本地文件包含
#include"filename"
先在源文件所在目录下查找,如果该头文件未找到,编译器就像查找库函数头文件一样在标
准位置查找头文件。如果找不到就提示编译错误
2、库文件包含
#include<filename.h>
查找头文件直接去标准路径下去查找,如果找不到就提示编译错误。
这样是不是可以说,对于库文件也可以使用 “” 的形式包含?
答案是肯定的
但是这样做查找的效率就低些,当然这样也不容易区分是库文件还是本地文件了
七、嵌套文件包含
一个复杂的项目往往需要很多个公共文件模块来辅助完成,这样子就避免不了重复包含而造成问价内容重复的问题。
如何解决: 用我们前面所用到的条件编译。
即每个头文件开头和结尾分别加上
#ifndef __TEST_H__
#define __TEST_H__
//文件内容
#endif
或者
#pragma once //这种方法是最简洁的