宏也可以带参数,其定义的一般形式为:#define标识符 字符串其中标识符是宏名,字符串中包含括号内指定的参数,称为宏扩展。这时由于带参数的宏从形式上看很像函数,为了统一,多数人在定义带参数的宏时喜欢使用小写字母。......
2023-11-18
带参数宏定义除了进行字符串替换外,还通过参数的代入实现更加复杂的宏代换功能,带参数宏定义的一般形式为:
#define 标识符(形参表) 表达式样式字符串
宏调用的格式为:
标识符(实参表)
带参数的宏调用时一般分为两个步骤。例如,对于宏定义:#define S(a,b)a*b进行宏调用的形式为T=S(3,2);,第一步将宏换为T=a*b;,第二步将实参代入换为T=3*2;。
使用带参数宏定义时,除了前面提到的使用宏定义预处理的注意事项外,还要注意下面几点:
①带参宏定义中,宏名和形参表之间不能有空格出现。
如:#define S(a,b) a*b
如果误写为:#define S (a,b) a*b,则将被认为是无参宏定义,宏名为S,字符串为(a,b) a*b。
②带参宏定义中,形式参数不分配内存单元,因此不必作类型定义。(www.chuimin.cn)
③在宏定义中的形参是标识符,而宏调用中的实参可以是表达式。为了避免当实参是表达式时的替换错误,定义时应将用于替换字符串中的所有形参用圆括号括起来。请比较并区别下面两种形式。
在C程序中使用带参数宏代换时,特别需要注意宏代换和函数调用的区别:
①函数调用时,先求出实参表达式的值,然后代入形式参数。而带参数的宏对实参表达式不作计算直接照原样代换,只是进行简单的替换。
②函数调用是在程序运行时处理的,因为形参要分配临时的存储单元。而带参数宏的展开则是在编译前进行的,在展开时并不分配内存单元,不进行值的传递处理,也没有返回值的概念。
③带参数宏的形式参数与函数中的形式参数不同,它没有确定的数据类型。在宏调用时随着代入的实际参数数据类型的不同,其运算结果的类型随之而变。
在程序设计时,采用宏定义还是函数需要根据情况而定,有关函数的部分已经在前面章节介绍过,与函数比较,宏定义的好处是宏替换是在编译阶段进行的,不占运行时间。同时它也有缺点,宏定义在预处理时原地进行替换展开,一般会增加代码的长度;此外,宏调用时并没有参数类型的检查,有可能引起不可预料的程序设计错误。
【例9.3】 带参数宏调用替换问题的理解示例。
在阅读理解上面程序时最容易得到的错误结果是:t=3000。事实上,宏替换后得到的表达式为:t=Min(a+b,c+d)*1000;→t=(a+b)<(c+d)?(a+b):(c+d)*1000;,从预处理完成的语句可以看出,在条件表达式中,当(a+b)<(c+d)的结果是1(非0)时,表达式最后的1000与应该取得的值毫无关系。程序运行的正确结果为:t=3。
有关C语言程序设计基础(第3版)的文章
宏也可以带参数,其定义的一般形式为:#define标识符 字符串其中标识符是宏名,字符串中包含括号内指定的参数,称为宏扩展。这时由于带参数的宏从形式上看很像函数,为了统一,多数人在定义带参数的宏时喜欢使用小写字母。......
2023-11-18
不带参数的宏定义一般形式是:#define宏名字符串例如:#definePI3.1415926其中,宏名用标识符表示,也就是前面讨论过的符号常量,上面示例中的PI就是宏名。正确使用“宏定义”的关键是宏调用时的“原样替换”。宏定义使用的简单示例。④宏定义不存在类型问题,它的参数也是无类型的。⑦宏定义允许嵌套。如:#defineN100#defineM2*N#defineK5+M⑧可以用#undef或不带替换字符串的宏定义终止宏定义的作用域。......
2023-11-20
包括函数名的命名和类型说明、形式参数的类型说明、变量定义和语句。下面举例说明主函数和自定义函数。函数的定义是平行的,彼此相互独立,不能嵌套定义。函数的类型和函数返回值的类型应保持一致。以两个数求和为例,说明函数的定义。......
2023-10-21
不带参数的宏用指定标识符来代替一个字符串。其一般格式为:#define标识符 字符串例如:#define PI 3.1415926用标识符PI来表示3.1415926,这叫做宏定义。但多数人习惯把所有的宏定义都写在文件的前面虽然这不是必须的。一个宏定义后,就可以在程序中使用了,例如:这个函数返回圆的面积。这里的1、0与一般意义下的1、0形式上没有任何不同,不容易让人理解,有了宏,我们就可以很方便地解决这个问题了。......
2023-11-18
图5.7两层函数嵌套调用示意图函数的嵌套调用即一个函数在被调用的过程中又调用了另外的一个函数。函数fac和powers的返回值类型均被设计为double型,其主要目的是为了避免n!x:0.5//0.5从键盘输入的数据0.50 powers of e=1.648721//程序执行结果......
2023-11-20
习惯把用typedef声明的类型名用大写字母表示,以便与系统提供的标准类型标识符区别。用tpyedef可以声明数组类型、字符串类型,使用比较方便。用typedef只是对已经存在的类型增加一个类型名,而没有创造新的类型。使用typedef有利于程序的通用与移植。有时程序会依赖于硬件特性,用typedef便于移植,例如,有的计算机系统int型数据占用2个字节,而另一些机器则占用4个字节。......
2023-11-18
C语言把括号、赋值、强制类型转换等都作为运算符处理,灵活使用各种运算符可以实现在其他高级语言中难以实现的运算,功能强大。另外,C语言还把括号、下标、强制类型转换、取地址等都作为运算符处理,并通过与算数运算符的组合达到不同的目的,从而使程序更加简洁明了。C语言具有超强的可移植性。总之,C语言在运算符方面是比较容易让人混淆的。......
2023-11-18
针对不同的实际应用,数据排序方法有很多种。本节介绍两种常用排序方法的基本思想和实现方法,帮助读者初步理解排序方法的计算机解决思路。②不考虑已排好序的数据,将剩下的数据作为待排序列。编写程序实现冒泡排序算法,对随机生成的10个3位整数按升序进行排序并输出。......
2023-11-20
相关推荐