6-3 宏定义 - 新闻资讯 - 云南小程序开发|云南软件开发|云南网站建设-昆明葵宇信息科技有限公司

159-8711-8523

云南网建设/小程序开发/软件开发

知识

不管是网站,软件还是小程序,都要直接或间接能为您产生价值,我们在追求其视觉表现的同时,更侧重于功能的便捷,营销的便利,运营的高效,让网站成为营销工具,让软件能切实提升企业内部管理水平和效率。优秀的程序为后期升级提供便捷的支持!

您当前位置>首页 » 新闻资讯 » 技术分享 >

6-3 宏定义

发表时间:2020-10-19

发布人:葵宇科技

浏览次数:41

6.3.1 宏定义的规则和使用解析

(1)宏定义的解析规则就是:在预处理阶段由预处理器来进行替换,这个替换是原封不动的替换。
(2)宏定义替换会递归进行,直到替换出来的值本身不再是一个宏为止。
(3)一个正确的宏定义式子本身分为3部分:第一部分是#define,第二部分是宏名,剩下的为第三部分。
(4)宏可以带参数,称为带参宏。带参宏的使用和带参函数非常像,但是使用上有一些差异。在定义带参宏时,每一个参数在宏体中引用时都必须加括号,最后整体再加括号,括号缺一不可。

#include <stdio.h> 
#define  X(a,b)		((a)+(b)) 
int main()
{	
	int a = 1,b = 2;	
	int c =3 * X(a,b);	
	printf("c = %d\n",c);	
	return 0;
}

6.3.2 宏定义示例1:MAX,求2个数中较大的一个

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

关键:
第一点:要想到使用三目运算符来完成。
第二点:注意括号的使用。

6.3.3 宏定义示例2:SEC_PER_YEAR,用宏定义表示一年有多少秒

#define  SEC_PER_YEAR	(365*24*60*60UL)

关键:
第一点:当一个数字直接出现在程序中时,它的类型默认是int;
第二点:一年有多少秒,这个数字刚好超过了int类型存储的范围

6.3.4 带参宏和带参函数的区别(宏定义的缺陷)

(1)宏定义是在预处理期间处理的,而函数是在编译期间处理的。这个区别带来的实质差异是:宏定义最终是在调用宏的地方把宏体原地展开,而函数是在调用函数处跳转到函数中去执行,执行完后再跳转回来。
注意:宏定义和函数的最大差别就是:宏定义是原地展开,因此没有调用开销;而函数是跳转执行再返回,因此函数有比较大的调用开销。所以宏定义和函数相比,优势就是没有调用开销,没有传参开销,所以当函数体很短(尤其是只有一句话时)可以用宏定义来替代,这样效率比较高。
(2)带参宏和带参函数的一个重要差别就是:宏定义不会检查参数的类型,返回值也不会附带类型;而函数有明确的参数类型和返回值类型。当我们调用函数时编译器会帮我们做参数的静态类型检查,如果编译器发现我们实际传参和参数声明不同时会报警告或错误。
注意:用函数的时候程序员不太用操心类型不匹配,因为编译器会检查,如果不匹配编译器会叫;用宏的时候程序员必须很注意实际传参和宏所希望的参数类型一致,否则可能编译不报错但是运行有误。
总结:宏和函数各有千秋,各有优劣。总的来说,如果代码比较多用函数适合而且不影响效率;但是对于那些只有一两句话的函数开销就太大了,适合用带参宏。但是用带参宏又有缺点:不检查参数类型。

6.3.5 内联函数和inline关键字

(1)内联函数通过在函数定义前加inline关键字实现。
(2)内联函数本质上是函数,所以有函数的优点(内联函数是编译器负责处理的,编译器可以帮我们做参数的静态类型检查);但是它同时也有带参宏的优点(不用调用开销,而是原地展开)。所以几乎可以这样认为:内联函数就是带了参数静态类型检查的宏。
(3)当我们的函数内函数体很短(譬如只有一两句话)的时候,我们又希望利用编译器的参数类型检查来排错,我还希望没有调用开销时,最适合用内联函数。

6.3.6 宏定义来实现条件编译(#define #undef #ifdef)

(1)程序有DEBUG和RELEASE版本,区别就是编译时有无定义DEBUG宏。

#include <stdio.h>
//这两行代码的效果加在一起就相当于没有定义DEBUG
//注销一个宏。如果前面有定义这个宏则取消这个宏,如果没有就无视掉
#define  DEBUG
#undef 	DEBUG 

#ifdef  DEBUG
#define	debug(x)	printf(x)
#else
#define   debug(x)
#endif 
int main(void)
{	
	debug("this is a debug info\n");	
	return 0;
}

相关案例查看更多