C语言:对于宏的一些概念及技巧

一、前言

  宏在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进行连接后返回

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Mr_zhang1911116/article/details/134272355