C语言的预处理和宏

C语言的编译预处理和宏

预处理

C语言的编译系统一般都包括预处理、编译和链接等部分,C代码编译时编译器一般的处理过程如下:

首先,运行预处理程序扫描源代码,对源程序中的预处理命令进行转换和处理
然后,运行编译程序,把源程序编译成目标代码
最后,运行链接程序,把目标代码链接成可执行文件

即替换,编译,链接三个过程

其中提到的预处理命令是指以**#号**开头的命令。在预处理过程中,这部分代码会被编译器索引处理成为我们所需要的代码段。

比如说使用
#include <math.h>
编译时,编译器会自动把math.h头文件中的code加入程序中,使我们的程序可以调用库中的函数。

不带参数的宏

而除去#include之外,还有一种比较常用的写法就是#define,我们称之为宏定义,比如
#define PI 3.14159
在程序编译过程中,PI会被自动替换为浮点数3.14159

当然,这是最为简单的宏定义的用法,即不带参数的宏,就是实现了简单的替换功能。在编程过程中,如果遇到了需要使用PI,RE,PR等量时,就可以考虑使用。这种用法可方便我们对代码的阅读和维护

这种宏的用法有以下几个需要注意的点:
1.宏定义一行写不下时,可以用换行标记""来续行,例如:

#define LONG_STRING this is\
not a very long string

2.字符常量、字符串和字符串中出现宏名,则不会被替换。例如:

#define HI hello 
printf("HI");

3.宏定义是允许嵌套的,灵活性比较高。例如:

#define X 5
#define Y X+1
#define Z Y*X

a = Z;

实际上a相当于做了一个运算的结果

代参数的宏

代参数的宏的使用方法有点类似函数,最简单的使用方法如下:

#define MULT(a,b) a*b
res = MULT(3,4)

这里的第二行相当于进行了一次相乘操作,然后把结果赋值给a。需要注意的是这种函数的调用方式可能会出现逻辑上的错误,比如:

#define MULT(a,b) a*b
res = MULT(3+2,4+5)

我们的逻辑语义会理解为,先做两个加法运算,再做乘法运算。然而实际编译过程中,被替换为代码:res = 3+2*4+5。实际上运行时,会先执行乘法运算,再执行两次加法。为了保证这种使用方法不会出现类似这样的逻辑错误,最好定义时使用如下:

#define MULT(a,b) (a)*(b)

使用宏的定义方式和调用函数有什么区别呢?
1.首先,函数调用时,实参要和形参的数据类型保持一致,不一致时,系统会自动把实参转换为形参的类型。但是宏只相当于简单的替换某个函数形式,不存在数据类型对应的问题
2.在编译过程中,带参数的宏对应的代码就已经被替换,实际执行过程中,相当于执行普通的代码。但是调用子函数的过程中,会出现压栈传参清栈的过程。使用宏定义一些简单的函数来实现子函数的功能,可以大大提高程序运行速度。

取消宏定义

常见的#define PI 3.14这样的命令,从开始到文件结束处都有效。有时全局有效的宏定义也会造成一些麻烦,而取消宏的命令,则可以把这种全局的宏局部化。

#define PI 3.14
#undef PI
#define PI 3.14159

宏定义和inline函数的区别

https://blog.csdn.net/wangliang888888/article/details/77990650
部分参考了这篇博客的内容。

inline函数的作用和宏定义非常像,我们首先看一下使用方法:

inline int MULT(int a,int b)
{ 
    return a*b;	
}

res = MULT(3,4);

inline函数也会进行代码的替换,但是替换之前会进行对应的语法检查,并且输入量也会有数据类型,相对宏定义更加安全,但是会消耗更多的内存空间。

程序包含多个.cpp文件时的实现和编译过程中是否会真正实现代码的替换。这部分细节可以具体的参考链接中的帖子。

多个文件中的函数相互调用

当程序中包含两个源文件时,如果第二个文件默认可以调用第一个文件中的函数,例如:

//File1.cpp
extern int eMax(int x, int y) 
// extern可以省略
 { 
 return x>y?x:y ;
 } 


//File2.cpp
void main()
{ int M;
 extern int eMax(int,int);
 // extern可以省略
 M=eMax(6,2);
} 

2文件可以调用1文件中的程序,我们称之为外部链接,外部链接是默认的属性。有时为了保证局部属性,我们会使用内部链接,如下:

//File3.cpp
static int iMax(int x, int y)
{ 
 return x>y?x:y ;
} 


//File4.cpp
void main()
{
 int M;
 int iMax(int,int);
 M=iMax(6,2);
} 

此时4调用3中的函数就会报错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值