预处理命令


要了解预处理我们得先从代码到可执行程序的过程来理解。

代码的编辑流程
代码的编辑流程可以分为四个步骤:
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
  • 20
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值