【C语言】——编译链接和预处理的深入了解

目录

一:翻译环境和编译环境:

1.翻译环境:

1).编译:

    1.预处理:

     2.编译:

     3.汇编:

2).链接:

2.运行环境:

二. 预处理:

1.预定义符号:

2.#define符号:

  1.#define定义常量:

2.#define定义宏:

3.带有副作用的宏参数 :

4.宏替换的规则: 

5.#和##的使用:

 1).#——把宏参数变成对应的字符串:

​编辑 

 2).##——可以将两个宏参数变成一个字符:   

6. #undef的使用:

三.头文件的包含:

1.头文件的包含方式:

 1).库文件包含:

 2).本地文件包含:

2.嵌套文件包含 :

总结:


 大家好,曳渔又来分享了!!

 希望可以获得大家的点赞和关注!!!


一:翻译环境和编译环境:

 在ANSI C的任意一种实现中,存在两种环境.                                                                                    第一种环境:翻译环境:在这个环境中源代码被转换为可执行的机器指令(二进制指令)。            第二中环境:编译环境:用于实际执行代码。


1.翻译环境:

由上图可知翻译环境分为两大类组成:编译和连接。 编译又分为预处理、编译、汇编。

1).编译:

    1.预处理:

   主要处理源文件中以#开头指令,比如:#include #define。

 规则:

·将所有的#define删除,并展开所有的宏定义

·处理所有的编译指令,比如:#if #ifdef #elif #else等

·处理#include预编译指令,将包含的有文件内容插入到该预编译指令的位置

·删除所有注释

·添加行号和文件名标识

·保留所有的#pragma的编译器指令

     2.编译:

  编译过程就是将预处理后的文件进行:词法分析、语法分析、语义分析及优化,生成相应的汇编代码文件

     3.汇编:

将汇编代码转变成成机器可执行的命令,每一个汇编语句几乎对应着一条机械指令

2).链接:

链接是一个复杂的过程,链接的时候需要把一堆文件链接在一起才生成可执行程序


2.运行环境:

 1.程序先被操作系统载入内存中。在独立的环境中,也可能是通过可执行代码置入只读内存来完成

 2.程序的执行开始在调用main函数

 3.开始执行程序代码,程序将使用一个运行时堆栈,存储函数的局部变量和返回地址。程序也可以同时使用静态内存,存储在静态内存中的变量在程序的整个执行过程中保留他们的值。

 4.之后终止程序,正常终止main函数,也可能是意外终止程序。


二. 预处理:


1.预定义符号:

C语言中设置了一些预定义符号,也是在预处理期间处理的。

那么如何使用呢?那咱们演示一下:


2.#define符号:

  1.#define定义常量:

语法:

举例: 

特例 :当定义的 suff 过长的话,可以分为多行写,除了最后一行外,每行后面都加一个(\)


2.#define定义宏:

#define有一个规定,可以把参数替换到文本中。

举例: 

再举一个大多数人都会错误的例子:

OK 这个代码的执行结果是什么呢?你这一看是不是以为很简单,这不就是6*6吗,不就是36吗,那你可错喽,掉坑里去了。 

看吧,结果是11,不是36,这是为什么呢?直接上图片: 就是这个原因,所以执行结果是11,而非36.

那么就有人问了,那我就想是用a+1*a+1(a=5)变成36。那要怎么实现呢?上图: 看如此便实现了,使其变成36.

注意事项: 参数列表的左括号必须与name紧邻,如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分


3.带有副作用的宏参数 :

当宏参数在宏中超过一次的时候,如果参数带副作用的话,那就会有危险。

那么副作用是什么呢?就是在表达式求值的时候出现的永久性的效果。咱们直接上例子:

 

这就是永久性的效果,那么是怎么改变的呢? 


4.宏替换的规则: 

1.首先,查看是否有#define定义的参数,如果有那么先替换。

2.替换后放到程序中原来的地方,对于宏,把他们的参数名替换成他们的值

3.最后,再次查看是否还有被宏定义的符号 

注意:

1.对于宏,不可以递归

2.当查找#define定义的符号是,字符串常量的内容不能查找


5.#和##的使用:

 1).#——把宏参数变成对应的字符串:

注意:一定要有参数

 

 2).##——可以将两个宏参数变成一个字符:   

那么把两个函数合并成一个函数的时候怎么写呢?这时就用到了我们的##了。 

这就是##的使用。


6. #undef的使用:

这就是#undef的使用了。


三.头文件的包含:

在写代码的时候我们会有两种写头文件的方法:库文件和本地文件两种。


1.头文件的包含方式:

 1).库文件包含:

 这种以 <> 的方式写的就是库文件包含。

查找方式:直接去标准路径下查找,如果找不到就报错。

 2).本地文件包含:

这种以 ""  表示的就是本地文件包含。

查找方式:先在源文件的目录下查找,如果找不到就去标准路径下查找,如果还是没有找到就报错


2.嵌套文件包含 :

 这样的头文件被编译四次的就是嵌套编译,但是过多的调用头文件,就会时编译的压力变大。

那么如何避免呢?有两种方法:


总结:

OK 喽今天的分享就到这里了,让我们下次再见啦,最后希望大家可以在我的分享中有所收获,

最最后希望可以获得大家的点赞和关注,那就再见啦~ 

  • 30
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值