C语言带参数的宏定义

C语言允许宏带有参数。在宏定义中的参数称为“形式参数”在宏调用中的参数称为“实际参数”,这点和函数有些类似。

对带参数的宏,在展开过程中不仅要进行字符串替换,还要用实参去替换形参。

带参宏定义的一般形式为:

#define 宏名(形参列表) 字符串

在字符串中可以含有各个形参。

带参宏调用的一般形式为:

宏名(实参列表);

例如:

#define M(y) y*y+3*y  //宏定义
// TODO:
k=M(5);  //宏调用

在宏展开时,用实参 5 去代替形参 y,经预处理程序展开后的语句为k=55+35。

示例 输出两个数中较大的数。

#include <stdio.h>
#define MAX(a,b) (a>b) ? a : b
int main(){int x , y, max;printf("input two numbers: ");scanf("%d %d", &x, &y);max = MAX(x, y);printf("max=%d\n", max);return 0;
}

运行结果:

input two numbers: 10 20
max=20

程序第 2 行定义了一个带参数的宏,用宏名MAX表示条件表达式(a>b) ? a : b,形参 a、b 均出现在条件表达式中。程序第 7 行max = MAX(x, y)为宏调用,实参 x、y 将用来代替形参 a、b。宏展开后该语句为:

max=(x>y) ? x : y;

带参宏定义

1 . 带参宏定义中,形参之间可以出现空格,但是宏名和形参列表之间不能有空格出现。例如把:

#define MAX(a,b) (a>b)?a:b

写为:

#define MAX  (a,b)  (a>b)?a:b

将被认为是无参宏定义,宏名 MAX 代表字符串(a,b) (a>b)?a:b。宏展开时,宏调用语句:

max = MAX(x,y);

将变为:

max = (a,b)(a>b)?a:b(x,y);

这显然是错误的。

2 . 在带参宏定义中,不会为形式参数分配内存,因此不必指明数据类型。而在宏调用中,实参包含了具体的数据,要用它们去替换形参,因此实参必须要指明数据类型。

这一点和函数是不同的:在函数中,形参和实参是两个不同的变量,都有自己的作用域,调用时要把实参的值传递给形参;而在带参数的宏中,只是符号的替换,不存在值传递的问题

示例 输入 n,输出 (n+1)^2 的值。

#include <stdio.h>
#define SQ(y) (y)*(y)
int main(){int a, sq;printf("input a number: ");scanf("%d", &a);sq = SQ(a+1);printf("sq=%d\n", sq);return 0;
}

运行结果:

input a number: 9
sq=100

第 2 行为宏定义,形参为 y。第 7 行宏调用中实参为 a+1,是一个表达式,在宏展开时,用 a+1 代换 y,再用 (y)*(y) 代换 SQ,得到如下语句:

sq=(a+1)*(a+1);

这与函数的调用是不同的,函数调用时要把实参表达式的值求出来再传递给形参,而宏展开中对实参表达式不作计算,直接按照原样替换

3 . 在宏定义中,字符串内的形参通常要用括号括起来以避免出错。例如上面的宏定义中 (y)*(y) 表达式的 y 都用括号括起来,因此结果是正确的。如果去掉括号,把程序改为以下形式:

#include <stdio.h>
#define SQ(y) y*y
int main(){int a, sq;printf("input a number: ");scanf("%d", &a);sq = SQ(a+1);printf("sq=%d\n", sq);return 0;
}

运行结果为:

input a number: 9
sq=19

同样输入 9,但结果却是不一样的。问题在哪里呢?这是由于宏展开只是简单的符号替换的过程,没有任何其它的处理。宏替换后将得到以下语句:

sq=a+1*a+1;

由于 a 为 9,故 sq 的值为 19。这显然与题意相违,因此参数两边的括号是不能少的。即使在参数两边加括号还是不够的,请看下面程序:

#include <stdio.h>
#define SQ(y) (y)*(y)
int main(){int a,sq;printf("input a number: ");scanf("%d", &a);sq = 200 / SQ(a+1);printf("sq=%d\n", sq);return 0;
}

与前面的代码相比,只是把宏调用语句改为:

sq = 200/SQ(a+1);

运行程序后,如果仍然输入 9,那么我们希望的结果为 2。但实际情况并非如此:

input a number: 9
sq=200

为什么会得这样的结果呢?分析宏调用语句,在宏展开之后变为:

sq=200/(a+1)*(a+1);

a 为 9 时,由于“/”和“”运算符优先级和结合性相同,所以先计算 200/(9+1),结果为 20,再计算 20(9+1),最后得到 200。

为了得到正确答案,应该在宏定义中的整个字符串外加括号:

#include <stdio.h>
#define SQ(y) ((y)*(y))
int main(){int a,sq;printf("input a number: ");scanf("%d", &a);sq = 200 / SQ(a+1);printf("sq=%d\n", sq);return 0;
}

由此可见,对于带参宏定义不仅要在参数两侧加括号,还应该在整个字符串外加括号
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/565038.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python实例 81,82

目录 81.题目&#xff1a;809*??800*??9*?? 其中??代表的两位数, 809*??为四位数&#xff0c;8*??的结果为两位数&#xff0c;9*??的结果为3位数。求??代表的两位数&#xff0c;及809*??后的结果。 82.题目&#xff1a;八进制转换为十进制 81.题目&#xf…

C语言带参宏定义和函数的区别

带参数的宏和函数区别&#xff1a; 宏展开仅仅是字符串的替换&#xff0c;不会对表达式进行计算&#xff1b;宏在编译之前就被处理掉了&#xff0c;它没有机会参与编译&#xff0c;也不会占用内存。而函数是一段可以重复使用的代码&#xff0c;会被编译&#xff0c;会给它分配内…

python实例 83,84

目录 83.题目&#xff1a;求0—7所能组成的奇数个数。 84.题目&#xff1a;连接字符串 83.题目&#xff1a;求0—7所能组成的奇数个数。 程序分析&#xff1a; 组成1位数是4个。 组成2位数是7*4个。 组成3位数是7*8*4个。 组成4位数是7*8*8*4个。 ...... #83 sum 0 …

C语言条件编译详解

我们要开发一个C语言程序&#xff0c;让它输出红色的文字&#xff0c;并且要求跨平台&#xff0c;在 Windows 和 Linux 下都能运行&#xff0c;怎么办呢&#xff1f; 这个程序的难点在于&#xff0c;不同平台下控制文字颜色的代码不一样&#xff0c;我们必须要能够识别出不同的…

python实例 85,86

目录 85.题目&#xff1a;输入一个奇数&#xff0c;然后判断最少几个 9 除于该数的结果为整数 86.题目&#xff1a;两个字符串连接程序 85.题目&#xff1a;输入一个奇数&#xff0c;然后判断最少几个 9 除于该数的结果为整数 程序分析&#xff1a;999999 / 13 76923 #85 a…

Python安装与环境变量的配置

Python安装与环境变量的配置 python下载&#xff1a; Python安装包下载地址 1 . 选择Windows系统的 2 . 选择相应的32/64位版本点击下载 python安装&#xff1a; 1 . 下载完成后&#xff0c;使用管理员身份进行安装 注意&#xff0c;勾选“Add Python 3.6 to PATH”选项…

python实例 87,88

目录 87.题目&#xff1a;回答结果&#xff08;结构体变量传递&#xff09; 88.题目&#xff1a;读取7个数&#xff08;1—50&#xff09;的整数值&#xff0c;每读取一个值&#xff0c;程序打印出该值个数的&#xff0a; 87.题目&#xff1a;回答结果&#xff08;结构体变量…

C语言指针是什么

情景进入 计算机中所有的数据都必须放在内存中&#xff0c;不同类型的数据占用的字节数不一样&#xff0c;例如 int 占用 4 个字节&#xff0c;char 占用 1 个字节。为了正确地访问这些数据&#xff0c;必须为每个字节都编上号码&#xff0c;就像门牌号、身份证号一样&#xf…

python实例 89,90

目录 89.电话数据加密 90.题目&#xff1a;列表的使用实例 89.电话数据加密 题目&#xff1a;某个公司采用公用电话传递数据&#xff0c;数据是四位的整数&#xff0c;在传递过程中是加密的&#xff0c;加密规则如下&#xff1a;每位数字都加上5,然后用和除以10的余数代替该数…

C语言指针变量的定义和使用

指针变量的含义 数据在内存中的地址也称为指针&#xff0c;如果一个变量存储了一份数据的指针&#xff0c;我们就称它为指针变量。 在C语言中&#xff0c;允许用一个变量来存放指针&#xff0c;这种变量称为指针变量。指针变量的值就是某份数据的地址&#xff0c;这样的一份数…

python实例 91,92,93,94

目录 Time 模块 91.时间函数举例1 92.时间函数举例2 93.时间函数举例3 94.时间函数举例4,一个猜数游戏&#xff0c;判断一个人反应快慢 Time 模块 Time 模块包含了以下内置函数&#xff0c;既有时间处理的&#xff0c;也有转换时间格式的&#xff1a; 序号函数及描述1tim…

python实例 95,96

目录 95.字符串日期转换为易读的日期格式 python第三方库 - dateutil 1.简介 2.安装 1&#xff0c;parse  2&#xff0c;rrule 96.计算字符串中子串出现的次数 95.字符串日期转换为易读的日期格式 #95 from dateutil import parser # from dateutil.parser import par…

C语言数组指针

数组&#xff08;Array&#xff09;是一系列具有相同类型的数据的集合&#xff0c;每一份数据叫做一个数组元素&#xff08;Element&#xff09;。数组中的所有元素在内存中是连续排列的&#xff0c;整个数组占用的是一块内存。以int arr[] { 99, 15, 100, 888, 252 };为例&am…

python实例 97,98

目录 97.从键盘输入一些字符&#xff0c;逐个把它们写到磁盘文件上&#xff0c;直到输入一个 # 为止 98.从键盘输入一个字符串&#xff0c;将小写字母全部转换成大写字母&#xff0c;然后输出到一个磁盘文件"test"中保存 97.从键盘输入一些字符&#xff0c;逐个把它…

Pycharm最新版本安装教程

下载安装 下载 pycharm官网 等待下载完成。 安装 下载好的exe&#xff0c;得到如下图所示&#xff0c;点击next 选择我们的安装位置&#xff0c;点击Next 把选框都勾选上&#xff0c;点击下一步 继续点击install 等待进度条加载完成&#xff0c;点击Next 如下图所示&…

python实例 99,100

目录 99.有两个磁盘文件A和B,各存放一行字母,要求把这两个文件中的信息合并(按字母顺序排列), 输出到一个新文件C中 100.列表转换为字典 99.有两个磁盘文件A和B,各存放一行字母,要求把这两个文件中的信息合并(按字母顺序排列), 输出到一个新文件C中 #99 import string fp o…

【蓝桥杯每日一练】 汉诺塔

目录 1.说明 2.解法 3.python实现 python全局变量使用方式&#xff1a; python全局变量和局部变量的区别&#xff1a; 1.说明 河内之塔(Towers of Hanoi)是法国人M.Claus(Lucas)于1883年从泰国带至法国的&#xff0c;河内为越战时北越的首都&#xff0c;即现在的胡志明市&…

XPath详解教程

目录 1. XPath 概览 2. XPath 常用规则 3. 准备工作 4.实例引入 5.所有节点 6. 子节点 7.父节点 8.属性匹配 9.文本获取 10.属性获取 11.属性多值匹配 12. 多属性匹配 13.按序选择 14. 节点轴选择 结语 1. XPath 概览 XPath 全称 XML Path Language &#xff0c;即 XML 路径语言…

【蓝桥杯每日一练】 斐波那契数列

目录 1.说明 2.原理 3.python实现 第一种&#xff1a; 第二种&#xff1a; 第三种 第四种 1.说明 Fibonacci为1200年代的欧洲数学家&#xff0c;在他的着作中曾经提到&#xff1a;「若有一只免子每个月生一只小免子&#xff0c;一个月后小免子也开始生产。起初只有一只免…

C语言二级指针

指针可以指向一份普通类型的数据&#xff0c;例如 int、double、char 等&#xff0c;也可以指向一份指针类型的数据&#xff0c;例如 int *、double *、char * 等。 如果一个指针指向的是另外一个指针&#xff0c;我们就称它为二级指针&#xff0c;或者指向指针的指针。 假设…