一、前言
宏在C语言中是一段有名称的代码段,在程序编译过程中,会将宏的内容被这段代码进行替换,常常用于定义一些常量、函数、代码块等,由于近年来发现许多公司进行面试时对于宏的面试题尤为多,故本文将对C语言中的宏的结构、使用以及注意事项进行详细介绍,有想法的小伙伴还可以在此基础上继续深入研究。
二、宏的基本结构
宏的基本结构如下:
例如:
#define PI 3.1415
#define number 50
#define MAX(x , y ) ((x)>(y)?(x):(y))
三、宏的基本使用
1、不携带参数的宏的定义
格式:
#define 宏名 表达式
例如:
#define PI 3.1415 //程序在预处理阶段会将PI替换为3.1415
注意事项:
(1)宏定义实质只进行替换,不进行计算
(2)宏名之后的表达式可以是常数、条件语句、函数等,预处理程序对它不做任何检查,程序在编译时才对宏替换的内容进行检查
(3)宏定义不是说明或语句,在行末不需要添加分号,如果用户在行末添加分号,则连分号一起进行替换
例如:
#define PI 3.1415 //将PI替换为“3.1415”
#define PI 3.1415; //将PI替换为“3.1415;”
(4)宏定义存在于全局,其作用域为全局作用域
例如:
xxx.c:
#include “stdio.h”
#include “stdlib.h”
#define PI 3.1415 //该宏存在于全局
int main()
{
printf(“PI=%f\n”,PI);
}
(5)宏定义允许发生嵌套,即一个宏可以使用另外一个已经存在的宏
格式:
#define number 50 ;
#define sum number*50 ; //宏的嵌套,将number替换成50,将sum替换成number*50
2、携带参数的宏的定义
定义:
#define 宏名(参数1,参数2,.....) 表达式
调用:
宏名(实参1,实参2,...........)
例如:
定义:
#define getMax(a,b) a>b?a:b //将getMax(a,b)替换成a>b?a:b的结果
调用:
int num=getMax(10,20) ;//调用之后getMax(10,20)返回最大值20
注意事项:
(1)考虑优先级问题,即如果宏定义中的表达式涉及运算符的优先级问题,需要用户及时考虑
第一种:考虑表达式中涉及优先级问题
例如:
代码如下:
#define getSum(a,b) a*b
int result1=getSum(40,20) ;
int result2 =getSum(10+30,20);
运行结果如下:
通过上面代码发现,最终计算的结果不一致,下面来分析一下原因:
1)
#define getSum(a,b) a*b
int result1=getSum(40,20) ; //目标是计算40*20的结果,编译器在执行时,将a替换为40,将b替换为20,故a*b的值为40*20,即800
2)
#define getSum(a,b) a*b
int result2 =getSum(10+30,20);//目标是计算(10+30)*20的结果,但是编译器在执行时,将a替换为10+30,将b替换为20,这时候a*b的值为10+30*20,即考虑优先级先执行乘法运算,再执行加法运算,所以结果为610
总结:
通过以上1)和2)两点,我们如何进行修改才能达到最初的目标40*20=800的结果?
修改如下:
代码:
#define getMax(a,b) (a) *b
int result1=getMax(10+30,20) //计算结果:(10+30)*20=800
int result2=getMax(40,20) //计算结果:(40)*20=800
运算结果:
第二种:考虑宏替换返回结果后涉及优先级问题
例如:
代码:
#define getSum(a,b) a+b
int result1=getSum(40,20)*3 ;//目标是计算(40+20)*3=180
运算结果:
通过上面代码发现,最终计算的结果是100,而不是180,下面来分析一下原因:
#define getSum(a,b) a+b
int result1=getSum(40,20)*3 ;//编译器在执行时,将a替换为40,将b替换为20,这时候result1=40+20*3,即先执行20*3=60,再执行40+60=100
总结:
通过上面代码,我们如何实现最初的目标(40+20)*3=180?
修改如下:
#define getSum(a,b) (a+b)
int result1=getSum(40,20)*3 //计算结果:(40+20)*3=180
运行结果:
(2)带参数的宏与函数的区别
1)宏比函数的运算速度快
使用宏:
使用函数:
2)宏不需要执行形参类型,而函数需要指定形参类型
例如:
宏:
#define getMax(a,b) a>b?a:b //a和b没有指定类型
函数:
void function(int a, int b); //a和b需要指定类型
3)宏不能够进行调试(因为宏替换工作是在预处理阶段)
4)宏不能实现递归
5)预处理符号“#”,如果设置一个表示将宏参数转为字符串,也通常被称为字符串转化运算符;如果设置两个表示将两个宏参数进行连接,称为连接运算符
一个“#”格式:
#define get_Str(x) #x //参数x将转换为字符串进行输出
两个“#”格式:
#define get_str(a,b) a##b //将参数a和b进行连接后返回