函数宏
什么是函数宏?
是函数?
它说:我是宏,也是函数,但我是你得不到的药(哼!)
下面是一串简单的代码,利用函数sqr_int和sqr_double对x和y求平方
int main()
{
int x=0;//记得初始化哦
double y = 0;
int ret1 = 0;
double ret2 = 0;
ret1 = sqr_int(x);
ret2 = sqr_double(y);
}
但是但是!!!
好麻烦
不同类型的变量需要不同的函数,接二连三地写出这种功能相近、名称又相似的函数,程序中就会充斥着这些似是而非的函数。
蓝廋想哭。。。
我就是大名鼎鼎的宏函数,看看我的本领吧!
#define sqr(x) x*x
int main()
{
int x=0;//记得初始化哦
double y = 0;
int ret1 = 0;
double ret2 = 0;
ret1 = sqr(x);
ret2 = sqr(y);
}
我是光我是风,我是唯一的神话。
函数和函数宏的区别
运行过程区别:
优点:函数式宏sqr是在编译时展开并填入程序的,因此只要是能用双目运算符*进行乘法计算的数据类型,都能使用函数式宏。
而函数定义则需为每个形参都定义各自的数据类型,返回值的类型也只能为一种。就这一点而言,函数较为严格。
函数为进行了一些复杂处理,如:参数传递(将实参的值复制到形参)函数调用和函数返回操作(程序流程的控制),返回值的传递
函数式宏所做的工作只是宏展开和填入程序,并不进行上述处理
综上: 根据以上特征,函数式宏或许能使程序的运行速度稍微提高一点,但是程序自身却有可能变得臃肿(如果宏展开后的表达式很复杂,那么在使用到它的所有地方都会填入这些复杂的表式)。
快乐吧唧一下,没有了
函数宏的副作用
都说是药三分毒,我也有几分毒性在身上哦...
记得(食用)使用时避开陷阱
辅药一
如果在宏名称sqr和紧邻其后的“(”之间插入空格,进行如下宏定义
#define sgr(x) ((x)*(x))
则sqr就会被编译器当作对象式宏,即程序中的 sgr 都会被代换为(x)((x)*(x))。
我们在定义函数式宏时必须注意不要误将空格写入宏名称和“(”之间。
辅药二
以下是计算二值之和的函数式宏
#define sum of(x,y) x+ y
我们使用下述语句来调用这个宏。
z=sum of(a,b)*sum of(c,d);
宏展开后的表达式不尽如人意。z=a+b*c+d;
保险起见,我们在宏定义时将每个参数以及整个表达式都用()括起来就不会出错了。
#define sum of(x,y) ((x) + (y))
这样表达式就能正确展开了。z=((a)+(b)) *((c) + (d));
辅药三
sqr(a++)展开后为((a++) * (at+))
每次展开,a 的值都会自增两次。在不经意间表达式被执行了两次
但函数不会,是由于其运行特征
高级一点的函数宏
#include<stdio.h>
#define puts_alert(str) { putchar(\a'); puts(str);}
int main()
{
int n;
printf("请输入一个整数:");
scanf("%d",&n);
if(n)
puts_alert(这个数不是0。");
else
putsalert(这个数是0。");
return 0;
}
函数式宏putsalert的定义是在puts 函数显示字符串str 时响铃。不过,这个程序在编译时会出错,不能运行。
main函数的if语句展开后如图8-2所示。if语会在第一个复合语)处结束,这时因为的 puts_alert(这个数不是0。");会被视为空语句。因此编译器会认为“没有 if,为何出现了else”
改良后的代码
#include<stdio.h>
#define puts_alert(str) (putchar(\a'); puts(str);)
int main()
{
int n;
printf("请输入一个整数:");
scanf("%d",&n);
if(n)
puts_alert(这个数不是0。");
else
putsalert(这个数是0。");
return 0;
}
细心的大家应该(没)发现,doge
答案就是逗号表达式。
函数式宏的展开
if (n)
(putchar('\a'),puts("这个数不是0。"));一表达式语句
else
(putchar(\a), puts("这个数是0。"));-表达式语句
如果宏定义中要代换两个以上的表达式,则使用逗号运算符连接,使其在语法上构成一个表达式。
补(逗号表达式):
对于使用逗号运算符的逗号表达式“a,b”,会按顺序判断表达式a和b。对左侧的表达式a仅进行判断,判断结果会被省去。而对右侧的表达式b进行判断所得到的类型和值,就是逗号表达式“a,b”的类型和值。例如,的值为3、的值为5时,若运行x=++i,++j;则1和都会递增,递增后的值6会被赋给x。