目录
要了解预处理我们得先从代码到可执行程序的过程来理解。
代码的编辑流程
代码的编辑流程可以分为四个步骤:
1.编辑
2.编译
3.运行
4.调试
其中预处理就是编辑步骤中的其中一部。(其并不是c语言系统自带的,其也是扩展的功能)
我们将编译过程展开:
编译过程其可分为:
1.预处理:
作用为:将代码中的预处理命令执行,并最终生成一个只有代码的.c文件
2.编译:对代码的语法进行检查,将c语言代码产生汇编代码
3.汇编:将汇编代码转变成机器代码
4.链接:将其他使用到的代码链接到一起生成可最终的可执行文件
linux实现编译过程详解:
使用代码举例:
预编译命令:
gcc -E 对应文件名.c -o 自定义文件名.i //其中 `-e` 辅助命令指的是对.c文件进行预处理变成c语言代码文件
编译命令:
gcc -S 对应文件名.i -o 自定义文件名.S //其中 `-S` 辅助命令指的是对.i文件进行编译变成汇编代码文件
汇编命令:
表示将汇编代码生成机器代码。
汇编命令:
gcc -c 对应文件名.s -o 自定义文件名.o //其中 `-c` 辅助命令指的是对.s文件进行编译变成机器语言代码文件
链接命令:
表示将机器语言代码生成可执行文件。
链接命令:
gcc -g 对应文件名.o -o 自定义文件名 //其中 `-g` 辅助命令指的是对.o文件进行链接变成可执行文件
预处理详解:
1.宏定义:
结构:
#define 标识符(宏名) 字符串(宏值)
注:
1.预处理命令都是#开头的。
2.宏名命名规则和标识命名规则一致。(一般建议写成大写,以便和小写字母代表的变量区分开)
3.预处理命令实际上是将宏名用宏值(预处理阶段的字符串)原样替换。//文本格式直接替换
4.应用:
a.提高代码可读性。
b.一改全改,方便代码全改。
5.作用域:(宏定义不一定写在代码最开头,任何位置都可以,但是要注意其作用域)
(从#define一直到#undef结束)
a.只有#define
所处行以下的范围才起作用。
b.直到#undef
宏名(宏结束标志位)
作用阶段:只有在预处理阶段才起作用
举例:
#define N 10//此处定义了一个宏名叫N,宏值为10 的宏
//表示之后见到的N都要在预处理阶段被替换成10,相当于用N来替换10
2.带参宏的定义:
带参宏也叫做宏函数
个人理解:但是他不是函数,宏函数只作用于预处理阶段,而函数则是在编译阶段经过调用才开始作用,其类似函数一样带了参数,但是他的参数没有值,没有类型,只是单纯的格式,在预处理阶段把对应参数处传过来的字符文本替换,然后在计算机编译阶段才关注其字符对应的含义,类型,值等
eg:
#define 宏函数名(参数) 宏值//宏值相当于要被替换成什么形式
#define Add(x,y) x+y
注意:
带参宏和函数的区别:
1…处理阶段不一样:
宏定义——在预处理阶段作用。
函数——在编译阶段起作用
2.使用不一样:
宏处理阶段就结束使用了,宏的使用本质上是文本的替换,可能最后会造成文件大小的略微增大。
宏的函数只是进行文本替换,不进行文本检测。
eg:
#define Multi at*i*i
#define ALter at
就如上方代码,按函数的定义以及引用上理解其是矛盾的,其先引用了才进行定义,但是在宏的模块其不会报错,代码预处理到这个命令就把所有的Multi换成at*i*i 的形式,然后再执行ALter预处理命令,将其对应的宏名换成at
而在函数上:
调用时才进行使用,本质上是函数代码的调用
参数:函数的参数是有类型的,编译阶段是要进行类型检查
3.应用不一样:
一般对于极小(一般指不超过5行的代码)的代码,考虑写成带参宏
4.宏的副作用:
由于宏只是文本替换,替换了之后有可能会改变表达式的结合性
#define A(a,b) a+b;
int ret =A(1,2)*8;
本意写成:(1+2)*8
以上代码被替换之后由于结合性的影响就变成了
ret = 1+2*8;
5.额外注意:
宏定义多个代码时必须写成一行(可以通过看其是否变色来确定是由被宏定义)
或者使用续行符\
,加在每行代码的最后注意如果续行符后面还有空格其就会失效
头文件包含:
包含头文件符号有< >
" "
< >
:默认到系统默认路径路径下寻找对应头文件。
" "
:表示到当前目录下寻找头文件,未找到才去系统默认目录
eg:
#include<stdio.h>
#include"file1.h"
条件编译:
1.ifdef 标识符
格式
#ifdef 标识符 //语句含义:若定义了标识符所对应的宏,那么就执行程序段1,
程序段1; //若没有定义对应的宏那么就执行程序段2
else
程序段2;
#endif
用途:
1.调试代码。
2.设计头文件。
3.防止头文件多次定义导致同一个作用域出现同名标识符
#ifndef A
#define A
int a
#endif
//语句含义:若没有定义宏A,那么就定义一个整形变量a,若已经定义了,那么就不在重复定义整形变量a
```c
***
## 2.#ifndef 标识符
格式
```c
#ifndef 标识符 //语句含义:若没有定义了标识符所对应的宏,那么就执行程序段1,
程序段1; //若定义对应的宏那么就执行程序段2
else
程序段2;
#endif
3.#if 表达式
格式
#if 表达式 //语句含义:表达式若为真,那么就执行程序段1,
程序段1; //若表达式若为假,那么就执行程序段2
else
程序段2;
#endif