【C语言从不挂科到高绩点】17-C语言中的宏定义
Hello!彦祖们,俺又回来了!!!,继续给大家分享 《C语言从不挂科到高绩点》课程!! 本节将为大家讲解C语言中的函数:
本套课程将会从0基础讲解C语言核心技术,适合人群:
- 大学中开设了C语言课程的同学
- 想要专升本或者考研的同学
- 想要考计算机等级证书的同学
- 想要从事C/C++/嵌入式开发的同学
================点个关注吧================
=========================================
八、C语言中的宏定义
8.1 宏定义概述
#define 宏定义命令,是 C 语言的预处理命令。所谓的预处理命令在代码编译之前需要做的处理。
所谓的宏定义,就是用一个标识符来表示一个字符串,如果在后面代码中出现了该标识符,那么就会全部替换成指定的字符串。
#include <stdio.h>
// 定义了一个宏,名字叫N,对应的字符串内容是100
// 表示在后续的代码中,但凡用到N就会被直接替换成100
#define N 100
int main(){
// N是宏,在编译代码之前,会先将N替换成100
// 在编译代码的时候,下面的代码已经变成了 int sum = 100+100;
int sum = N+N;
int result = N*N;
printf("sum=%d,result=%d\n", sum,result);
return 0;
}
上面案例中,在编译代码之前,代码中所有的 N 都会被替换成 100
宏定义的一般格式为:
#define 宏名 字符串
8.2 宏定义的使用场景
当程序中有反复需要使用的且比较复杂的表达式的时候,可以将这个表达式定义成宏。
#define M (n*n+3*n)
它的作用,就是用指定的标识符 M 来表示(n*n+3*n),在编写代码的时候需要用到(n*n+3*n)的时候,就可以用 M 来代替
#include <stdio.h>
#define M (n*n+3*n)
#define K n*n+3*n
int main(){
int n = 0;
printf("请输入一个整数:");
scanf("%d",&n);
int sum = 3*M+4*M+5*M; // 每一个M都会被替换成(n*n+3*n)
// 经过预处理之后 int sum = 3*(n*n+3*n)+4*(n*n+3*n)+5*(n*n+3*n)
printf("sum=%d\n", sum);
int result = 3*K+4*K+5*K;
printf("result=%d\n", result);
// 经过预处理之后 int sum = 3*n*n+3*n+4*n*n+3*n+5*n*n+3*n
return 0;
}
需要注意的问题:当做宏替换(宏展开)的时候,是将宏名原封不动的替换成字符串。不会添加任何符号也不会删除任何符号。
8.3 宏注意事项
- 宏定义时,宏名表示一个字符串,宏定义不是语句,在行末不需要加分号,如果加上分号,就会连同分号一起替换。
- 宏定义必须写在函数外,它的作用域为从宏定义命令开始到源程序结束。如果要提前终止宏,可以使用#undef 命令
#include <stdio.h>
// 宏定义默认情况下作用范围从定义开始,到程序结束
#define PI 3.1415926 // 安装PI
void func();
int main(){
printf("main:半径为3的圆的面积为:%lf\n",PI*3*3 );
func();
return 0;
}
// 如果要禁用宏,可以使用#undef
#undef PI // 卸载PI
void func(){
printf("func:半径为3的圆的面积为:%lf\n",PI*3*3 );
}
终止禁用宏之后,如果再使用宏,就会出现如下的错误:
- 宏定义允许嵌套,在定义宏的字符串中可以使用已经定义好的宏名。宏替换(宏展开)的时候会层层替换。
#include <stdio.h>
// 宏定义默认情况下作用范围从定义开始,到程序结束
#define PI 3.1415926 // 安装PI
#define S PI*r*r // 在名字为S的宏中,使用了名字为PI的宏
void func();
int main(){
printf("main:半径为3的圆的面积为:%lf\n",PI*3*3 );
int r = 3;
// 第1步:宏展开:S被替换成:PI*r*r
// 第2步:宏展开:PI被替换成3.1415926 :3.1415926*r*r
// 最终输出语句中S会被替换成:3.1415926*r*r
printf("【main】:半径为3的圆的面积为:%lf\n",S);
func();
return 0;
}
// 如果要禁用宏,可以使用#undef
//#undef PI // 卸载PI
void func(){
printf("func:半径为3的圆的面积为:%lf\n",PI*3*3 );
}
需要注意的问题:如果宏替换的字符串中,存在变量名。那么在使用宏之前,一定要先定义这些变量。上面代码中 S 的宏中 PI*r*r 中包含了变量 r,在使用 S 之前一定要先定义 r。
所以:一般建议宏名全大写,目的在于可以区分那些是宏名哪些是变量名。
- 可以用宏定义表示数据类型
#include <stdio.h>
#define UINT unsigned int
int main(){
UINT a=10; // 宏替换之后: unsigned int a = 10;
UINT c,b=20;
printf("a=%d,b=%d,c=%d \n",a,b,c );
}
总体来说,宏展开只是做的简单字符串替换,由预处理器在编译代码之前进行处理的。
8.4 带参数的宏
C 语言中允许带参数的宏,在宏定义中的参数,称为形式参数,在宏调用中的参数称为实际参数。
带参数的宏定义的一般格式为:
#define 宏名(参数列表) 字符串
带参数的宏调用的一般形式为
宏名(实参列表)
比如:
#define M(y) y*y+y*3
k = M(5); // 宏调用
在预处理阶段(编译之前),用实际参数 5 去代替形式参数 y,经过预处理之后的语句
k = 5*5 + 5*3
【案例代码】
#include <stdio.h>
#define MAX(a,b) a>b?a:b
int main(){
int x,y ,max;
printf("请输入两个数:");
scanf("%d %d",&x,&y);
max = MAX(x,y); // 宏替换之后:x>y?x:y
printf("最大值为:%d\n",max );
return 0;
}
需要注意的问题:带参数的宏和函数区别
- 宏展开仅仅是字符串的替换,不会对表达式进行计算。
- 宏在编译之前就已经被处理掉了(做好了字符串替换了),宏没有机会参与编译,宏不会占用内存
- 函数是一段可以重复使用的代码,会被编译,会给它分配内存,每次调用函数,就是执行这块内存中的代码。
【练习】定义一个宏,来计算指定天数一共有多少秒
【参考代码】
#include <stdio.h>
// 普通的宏替换
// #define SEC day*24*60*60
// 带参数的宏
// #define SEC(n) n*24*60*60
// 宏嵌套
#define SEC 24*60*60
#define TIM day*SEC
int main(){
printf("请输入一个天数:");
int day = 0;
scanf("%d",&day);
// printf("%d天一共有%d秒\n",day, SEC);
// printf("%d天一共有%d秒\n",day, SEC(day)); // day*24*60*60
printf("%d天一共有%d秒\n",day, TIM);
return 0;
}
8.5 #和##用法
#用来将宏参数转换成字符串,也就是在宏参数的开头和末尾加上引号,比如:
#define STR(s) #s
会将参数 s 变成字符串,s 会用双引号包裹起来。
#include <stdio.h>
#define STR(s) #s
int main(){
printf("%s\n", STR(哈哈) );
printf("%s\n", STR("哈哈") );
return 0;
}
运行效果:
##称为连接符,用来将宏参数或者其他字符串串联起来,比如:
#define CON1(a,b) a##e##b
#define CON2(a,b) a##b##00
【参考代码】
#include <stdio.h>
#define CON1(a,b) a##e##b
#define CON2(a,b) a##b##00
int main(){
printf("%f\n",CON1(8.5,2) ); // 8.5e2
printf("%d\n",CON2(8,5) ); //8500
return 0;
}
运行效果:
----------------------------------------------------------------------
分享不易,耗时耗力,喜欢的同学给个关注和赞吧
承接毕设指导,技术答疑,学习路上想要找私人教练的同学可以私信我
更多学习资料,公众号:墨轩学习网,B站:墨轩大楼
----------------------------------------------------------------------
另有下图需求的也记得私信我哟,专业班子