c语言——程序环境与预处理

编译环境

预处理

预处理是文本操作,主要进行以下三个操作。

  1. 将注释替换成空格,也可以说是将注释删除
  2. 将头文件所包含的内容展开
  3. 将#define所定义的符号进行替换

编译

编译:将c语言代码翻译成汇编代码。

  1. 语法分析
  2. 词法分析
  3. 语义分析
  4. 符号汇总(符号汇总所汇总的符号是全局的,例如自定义函数名,和main函数)

汇编

汇编:把汇编代码翻译成二进制指令,并生成.o文件(目标文件)。同时将汇总的符号生成符号表。

链接

链接:链接目标文件和链接库生成可执行程序(二进制的程序)

  1. 合并段表
  2. 符号表的合并与重定位

 

运行环境

程序运行的过程:

  1. 程序必须载入内存中。在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。
  2.  程序的执行便开始,接着便调用main函数。
  3.  开始执行程序代码。这个时候程序将使用一个运行时堆栈,存储函数的局部变量和返回地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程一直保留他们的值。
  4. 终止程序(正常终止main函数,也有可能是意外终止)

预处理指令

#define

#define是所定义的符号或宏都是直接替换。例如#define M 5,那么在后续的代码中M会直接被替换成5

  1. 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先 被替换。
  2. 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换。
  3. 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上 述处理过程。

#define定义宏

 可能有人会好奇,为什么要添加如此多的括号。接下来我一一举例。

如图,我们预想的结果应该是36,即为3x(3x4),但因为#define是直接替换,所以导致其变成了3*2+1*1+3,按照优先级先算了乘法。所以要在x*y加上括号变成(x*y)。在以下代码中,即便改成(x*y)也还不行,替换时变成了3x(2+1*1+3),括号内部仍未变成我们想要的3x4,括号内的结果为6。所以正确的做法应该是改成((x)*(y)).

 另外,像x+,++x,x--,--x这类自加自减的参数万不可扔进宏里,天知道他会自加自减多少次。

宏与函数的区别

把宏名全部大写,函数名不要全部大写。

属性#define定义宏函数
代码长度每次使用时,宏代码都会被插入到程序中。除了非常小的宏之外,程序的长度会大幅度增长函数代码只出现于一个地方;每次使用这个函数时,都调用那个地方的同一份代码。
执行速度更快存在函数的调用和返回的额外开销,所以相对慢一些。
操作符优先级宏参数的求值是在所有周围表达式的上下文环境里,除非加上括号,否则邻近操作符的优先级可能会产生不可预料的后果,所以建议宏在书写的时候多些括号。函数参数只在函数调用的时候求值一次,它的结果值传递给函数。表达式的求值结果更容易预测。
带有副作用的参数参数可能被替换到宏体中的多个位置,所以带有副作用的参数求值可能会产生不可预料的结果。函数参数只在传参的时候求值一次,结果更容易控制。
参数类型宏的参数与类型无关,只要对参数的操作是合法的,它就可以使用于任何参数类型。函数的参数是与类型有关的,如果参数的类型不同,就需要不同的函数,即使他们执行的任务是
相同的。
调试宏可以调试,但调试起来不方便。函数是可以逐语句调试的。
递归宏是不能递归的。函数是可以递归的

#undef

#undef用于移除一个宏定义

如图所示,因为移除了add的定义,所以12行处变成了未定义标识符。

#include

  • 本地文件包含:#include "stdio.h"
  • 查找策略:先在源文件所在目录下查找,如果该头文件未找到,编译器就像查找库函数头文件一样在标 准位置查找头文件。 如果找不到就提示编译错误。
  • 库文件包含:#include <stdio.h>
  • 查找策略:查找头文件直接去标准路径下去查找,如果找不到就提示编译错误。

库文件也可以用""来包含,但不推荐,查找的效率会下降。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值