宏与宏函数

宏与宏函数

#include "stdafx.h"


#if  0

1.宏的本质是,替换

2.我们常将短小精悍的函数进行宏化,这样可以嵌入到代码中,
减少调用的开销。但是代价就是,编译出的文件可能会变大

3.尽量少用宏函数,能看的懂别人写的宏函数即可。C++中
的 inline 函数(内联函数)己经取代了宏函数作用


----带参数的宏与函数区别如下

1.函数调用时,先求实参表达式的值,然后传递给形参,而使用带参数的宏只是进行简单的字符串替换,
不进行表达式求值

2.函数调用是在程序运行时处理的,为形参分配临时的内存空间,而宏展开是在编译前进行的,
在展开时并不分配内存单元,不进行值的传递,同样也没有“返回值”的概念

3.函数的实参和形参都必须定义类型,二者的类型要求一致,如不一致,则要进行类型转换,
而宏不存在类型问题,因为宏名无类型,它的参数也无类型,仅是字符串替换,展开时代入
指定的字符串即可。宏定义时,字符串可以是任何类型的数据

4.调用函数只会获得一个返回值,而宏则不然,可设法得到几个返回值

5.宏展开会促使源程序变长,因为每次展开都使程序增长,而函数调用不会增加代码长度

6.宏替换不占用运行时间,只占用编译时间,而函数调用则占用运行时间用于分配单元,
保存现场,值传递,返回等。所以宏替换可以提供程序的执行效率,但编译时间会变长


----宏的引入带来的好处

1.宏定义的引入可方便程序的修改。使用简单宏定义,可用宏替换那些在程序中经常使用的常量,
当需要修改该常量时,不用对整个程序进行修改,只修改宏定义的字符串即可,而且当常量比较长时,
可以用较短,有意义的标识符来编写程序,这样更方便

2.提高程序的运行效率

使用带参数的宏定义既可完成函数调用的功能,又能减少系统开销,提高运行效率。宏定义是在预
处理阶段就进行了宏展开,在执行时不需要替换。宏定义可完成简单的操作,但复杂的操作还是要
由函数来完成,而且宏定义所占用的目标代码空间相对较大,所以在使用时要依据具体情况决定是
否使用宏定义。

3.#define预处理完全没有把C++的作用域纳入考量,绝大多数C++实现都是封装在命名空间里,
这样的做法有很多优点。但不幸的是,#define的作用域并未被限定在名字空间里

4.宏还可以用于条件编译


宏要注意的问题

1.由操作符优先级引起的问题:
由于宏只是简单的替换,宏的参数如果是复合结构,那么通过替换之后可能由于各个参数之间的操
作符优先级高于单个参数内部各部分之间相互作用的操作符优先级,如果不用括号保护各个宏参数,
就会产生意想不到的情况

2.使用宏定义,不允许参数发生变化
#include "stdafx.h"
#define sqrt(a) ((a)*(a))

int fsqrt(int a)
{
	return a * a;
}

int main()
{
	int a = 10, b = 10;
	int r1, r2;
	r1 = sqrt(a++);
	r2 = fsqrt(b++);

	printf("a=%d,b=%d,r1=%d,r2=%d\n", a, b, r1, r2);

    return 0;
}
这段程序的最终结果是a=12,b=11,r1=100,r2=100,这所以a=12,是因为在替换的时候,
a++被执行了两次。要避免这种行为,就要使宏参数不发生变化,如a++;r1=sqrt(a);

#endif

定义宏应该注意的是:应该用括号将宏定义中的参数和整个宏括起来

//一行如果写不下需要换行写 必须加上\(续行符)来连接,
//但是\前面一定不能有空格,否则会出错
#define PI      3.141\
5926


#define  M   2+3
#define  N  (2+3)


//带参宏(宏函数)
#define X(a,b)   a*b
#define S(a,b)  ((a)*(b))
//内部括号保证内部优先级 外部括号保证外部优先级


//普通函数
int  func(int i)
{
	return i *i;
}

//宏函数
#define SQ(i)  ((i)*(i))

//取消宏或宏函数
//#undef + 宏或宏函数 从此以下都不能用了


int _tmain(int argc, _TCHAR* argv[])
{
	printf("%d\n", N * 3);
	printf("%d\n", M * 3);//没加括号的宏计算时相当于 2+3*3=11
	printf("%f\n", PI);

	int a = X(2 + 2, 2 + 3); //相当于 2+2*2+3=9
	int b = S(2 + 2, 2 + 3); // (2+2)*(2+3)=20
	printf("a=%d\n", a); 
	printf("b=%d\n", b);

	printf("===========================================\n");

	int i = 1;
	while (i <= 5)
	{
		printf("%d\n",SQ(i++) ); // printf("%d\n",((i++)*(i++)) );
		//开始i=1 1*1=1 然后1执行俩个++变为3 3*3=9 3执行俩++变为5 5*5=25
		//有的环境下会不一样 可能出现2  12  30
	}

	printf("===========================================\n");

	int p = 1;
	while (p<=5)
	{
		printf("%d\n", func(p++));
	}

	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值