小白初学 | 小白初学 之 “宏”(内有干货,从小白开始的基础宏学习)

5.16 待更新ing (内容有点长,有目录索引!!!)

“我真的太小白了” & 心路历程
  • 话说我接触到宏是在咱老师布置的一个刷题OJ平台里面,因为是小白,想着多刷点题来学习和巩固下基础,看到跟宏有关的题就觉得挺难的,我没看着过这个,一直不敢尝试。
  • 但就偏今天心情消极,外边明朗的天空也一下放阴沉,想用啥吊起自己学习的激情,就决定一试。
  • 没想到这东西竟然就是我以前使用过的#define N 20的理论部分的名字??
  • 以前只知道用这个来确定常量的值,使它不会被轻易改变,害,我真是太小白了,被自己气死。

实干的货来了!(附参考资料的链接)

我在这里引用了我在百度中搜索学习得到的部分po主的回答,以及编程实践中题解作者的相关知识来学习,在这些基础上结合了我自己的思考和理解,链接附于下:

宏定义解释的po主–原回答链接 在这里插入图片描述
带参数的宏的po主–原回答链接在这里插入图片描述
编程实践1-宏定义的练习–原po主题解链接
在这里插入图片描述
编程实践2- 带参数宏定义练习–原po主题解链接
在这里插入图片描述

什么是宏???| 宏的定义解释

,即宏定义,也称宏代换,宏替换,简称“宏”。

宏定义是C提供的三种预处理功能的其中一种,这三种预处理包括:宏定义、文件包含、条件编译。

格式:
#define 标识符 字符串

其中的标识符就是所谓的符号常量,也称为“宏名”。

预处理(预编译)工作也叫做宏展开:将宏名替换为字符串。

掌握"宏"概念的关键是“”。
一切以换为前提、做任何事情之前先要换

我们更需要准确理解*之前就要“换”。*这个概念
在对相关命令或语句的含义和功能作具体分析之前就要换
例:
#define PI 3.1415926
把程序中出现的PI全部换成3.1415926

说明:
(1)宏名一般用大写
(2)使用宏可提高程序的通用性和易读性,减少不一致性,减少输入错误和便于修改。例如:数组大小常用宏定义
(3)预处理是在编译之前的处理,而编译工作的任务之一就是语法检查,预处理不做语法检查。
(4)宏定义末尾不加分号;
(5)宏定义写在函数的花括号外边,作用域为其后的程序,通常在文件的最开头。
(6)可以用#undef命令终止宏定义的作用域
(7)宏定义不可以嵌套
(8)字符串" "中永远不包含宏
(9)宏定义不分配内存,变量定义分配内存。
(10)宏定义不存在类型问题,它的参数也是无类型的。

带参数的宏:

除了一般的字符串替换,还要做参数代换

格式:
#define 宏名(参数表) 字符串

例如:#define S(a,b) a*b
area=S(3,2);第一步被换为area=ab; ,第二步被换为area=32;

带参数的宏,这样的话就类似于函数调用,有一个哑实结合的过程:
(1)实参如果是表达式容易出问题
#define S(r) r*r
area=S(a+b);
第一步换为area=rr;,第二步被换为area=a+ba+b;
正确的宏定义是#define S(r) (r)*(r)
(2)宏名和参数的括号间不能有空格
(3)宏替换只作替换,不做计算,不做表达式求解
(4)函数调用在编译后程序运行时进行,并且分配内存。宏替换在编译前进 行,不分配内存
(5)宏的哑实结合不存在类型,也没有类型转换。
(6)函数只有一个返回值,利用宏则可以设法得到多个值
(7)宏展开使源程序变长,函数调用不会
(8)宏展开不占运行时间,只占编译时间,函数调用占运行时间(分配内存、保留现场、值传递、返回值)

编程实践:

实践1:
题目 1037: [编程入门]宏定义的练习

时间限制: 1Sec 内存限制: 128MB 提交: 5418 解决: 4199

题目描述
输入两个整数,求他们相除的余数。用带参的宏来实现,编程序。
输入
a b两个数
输出
a/b的余数
样例输入
3 2
样例输出
1

作者代码参考:
#include<stdio.h>
#define DIF(a,b) d = a - b * (a / b)
int main(void)
{
    
    
    int n,m,d;
    scanf("%d %d",&n, &m); 
    DIF(n,m);
    printf("%d", d);
    getchar();
    return 0;
 }
myCode(带注释和思考)
#include<stdio.h>

#define Remainder(a,b) d = a - b * (a / b)

//取余数的函数 Remainder()里面带两个实参a,b,即a/b
//根据余数相关性质和定义(理论知识在下面)a/b 的结果可运用公式a - b * (a / b)计算并赋值给d
//使用#define Remainder(a,b) d = a - b * (a / b)结果也正确,但可能遇到复杂的数字会出错(我还没测试,只是猜测)
//这里的宏的运用就是  ??? 是啥呢 还没搞懂 

int main(void)
{
    
    
    int n,m,d;
    
    scanf("%d %d",&n, &m); //输入要相除的两个数 
    
    Remainder(n,m);//求出结果??? 
    
    printf("%d", d);//打印结果 
    
    //getchar();//???这一步用来干嘛呢没搞懂??? 
	//将这一步注释掉程序也可运行且结果正确 
	
    return 0;
 }
关于余数的相关知识运用(引用该题解作者)

在整数的除法中,只有能整除与不能整除两种情况。当不能整除时,就产生余数,取余数运算:a mod b = c(b不为0) 表示整数a除以整数b所得余数为c,如:7÷3 = 2 ······1。
余数有如下一些重要性质(a,b,c均为自然数):
(1)余数和除数的差的绝对值要小于除数的绝对值(适用于实数域);
(2)被除数=除数×商+余数;
除数=(被除数-余数)÷商;
商=(被除数-余数)÷除数;
余数=被除数-除数×商。
(3)如果a,b除以c的余数相同,那么a与b的差能被c整除。例如,17与11除以3的余数都是2,所以17-11能被3整除。
(4)a与b的和除以c的余数(a、b两数除以c在没有余数的情况下除外),等于a,b分别除以c的余数之和(或这个和除以c的余数)。例如,23,16除以5的余数分别是3和1,所以(23+16)除以5的余数等于3+1=4。注意:当余数之和大于除数时,所求余数等于余数之和再除以c的余数。例如,23,19除以5的余数分别是3和4,所以(23+19)除以5的余数等于(3+4)除以5的余数。
(5)a与b的乘积除以c的余数,等于a,b分别除以c的余数之积(或这个积除以c的余数)。例如,23,16除以5的余数分别是3和1,所以(23×16)除以5的余数等于3×1=3。注意:当余数之积大于除数时,所求余数等于余数之积再除以c的余数。例如,23,19除以5的余数分别是3和4,所以(23×19)除以5的余数等于(3×4)除以5的余数。

实践2:

题目 1036: [编程入门]带参数宏定义练习

时间限制: 1Sec 内存限制: 128MB 提交: 5213 解决: 4379

题目描述
定义一个带参的宏,使两个参数的值互换,并写出程序,输入两个数作为使用宏时的实参。输出已交换后的两个值。
输入
两个数,空格隔开
输出
交换后的两个数,空格隔开
样例输入
1 2
样例输出
2 1

作者代码参考:
#include <stdio.h>
#include <math.h>
#define chang(a,b) t=a,a=b,b=t;
int main()
{
    
    
    int a,b,t;
    scanf("%d %d",&a,&b);
    chang(a,b);
    printf("%d %d",a,b);
    return 0;
}
myCode(带注释解释和自我思考,两种方法)
#include<stdio.h>
#include <math.h>
#define exchange(a,b) t=b,b=a,a=t;
//可以使用中间变量的办法 (t=b;b=a;a=t;) 来交换两个数的值
//或者需要寻找两数直接直接的数量关系
//利用两数的和差关系(a=a+b,b=a-b,a=a-b)来解决交换的问题 
int main()
{
    
    
    int m,n,t; //宏中遇到不是实参的参数,要在主函数中定义 
	//可以使用和宏上面一样的字母定义,也可以重新定义两个变量名 
    scanf("%d %d",&m,&n);
	//之前结果老是输出错误,原因:scanf("%d,%d",&m,&n); 多了个逗号,理由?? 
    exchange(m,n);//一定要有这一步!不然结果会出错 
    printf("%d %d",m,n);
    return 0;
}
解题思路+宏的参数知识具体讲解(引用该题解作者)

解题思路:
C语言中的宏允许带有参数,包含形参和实参,在宏定义中的参数称为形式参数,在宏调用中的参数称为实际参数,无参宏的宏名后不带参数,其定义的一般形式为:

#define 标识符 字符串; 例如#define m a*b;

其中ab的值就是m,在主函数中m就是调用ab;

带参宏定义的一般形式为:
#define 宏名(形参表) 字符串;
在字符串中含有各个形参。
带参宏调用的一般形式为:

#define y(a,b) t=a,a=b,b=t;
宏名(实参表),其中a,b就是实参,通过在主函数中输入,然后通过宏定义的预处理,也就是后面的字符串(t=a,a=b,b=t)来运算,在主函数中得到调用。

注意事项:
一般我们在定义宏的时候要根据形参和实参的需要来选择,该题中我们要运用到实参

实践3:
实践4:
实践5:

猜你喜欢

转载自blog.csdn.net/Kd_2number/article/details/106159498