【C语言从不挂科到高绩点】17-C语言中的宏定义

Hello!彦祖们,俺又回来了!!!,继续给大家分享 《C语言从不挂科到高绩点》课程!! 本节将为大家讲解C语言中的函数:

本套课程将会从0基础讲解C语言核心技术,适合人群:

  1. 大学中开设了C语言课程的同学
  2. 想要专升本或者考研的同学
  3. 想要考计算机等级证书的同学
  4. 想要从事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 宏注意事项

  1. 宏定义时,宏名表示一个字符串,宏定义不是语句,在行末不需要加分号,如果加上分号,就会连同分号一起替换。
  2. 宏定义必须写在函数外,它的作用域为从宏定义命令开始到源程序结束。如果要提前终止宏,可以使用#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 );
}

终止禁用宏之后,如果再使用宏,就会出现如下的错误:

  1. 宏定义允许嵌套,在定义宏的字符串中可以使用已经定义好的宏名。宏替换(宏展开)的时候会层层替换。
#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。

所以:一般建议宏名全大写,目的在于可以区分那些是宏名哪些是变量名

  1. 可以用宏定义表示数据类型
#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;
}

需要注意的问题:带参数的宏和函数区别

  1. 宏展开仅仅是字符串的替换,不会对表达式进行计算。
  2. 宏在编译之前就已经被处理掉了(做好了字符串替换了),宏没有机会参与编译,宏不会占用内存
  3. 函数是一段可以重复使用的代码,会被编译,会给它分配内存,每次调用函数,就是执行这块内存中的代码。

【练习】定义一个宏,来计算指定天数一共有多少秒

【参考代码】

#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站:墨轩大楼

----------------------------------------------------------------------

另有下图需求的也记得私信我哟,专业班子


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

听潮阁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值