笔记3:预处理器-宏定义
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了笔记3:预处理器-宏定义相关的知识,希望对你有一定的参考价值。
#define指令称为宏定义指令,通常用#define指令来定义一个宏用来代表其他东西的一个名字(如常量表达式等)。通常来说预处理器会通过将宏的名字和它的定义存储在一起来响应#define指令。当这个宏在后面的程序中使用到时,预处理器会"扩展"宏,将宏替换为其定义值。
简单的宏
简单的宏的定义格式: #define 标识符 替换列表
如:
#define DTE_LEN 80 #define TRUE 1 #define FALSE 0 #define PI 3.1415926 #define CP ‘\r‘ #define EOS ‘\0‘ #define MEM_ERR “Error:not enough memory”
注意:不要在宏定义中放置任何额外的符号,否则它们将会被作为替换列表的一部分(常见的错误是在宏定义中使用=和;)。
使用#define来为常量命名的优点:
1.程序会更易读。如#define PI 3.1415926就更易使他人读懂自己的程序
2.程序会更易修改。
3.可以帮助避免前后不一致或键盘输入错误。
4.可以对C语言做小的修改。如:
#define BEGIN { #define END } #define LOOP for(;;) //实现一个无限循环
5.对类型的重命名。如:(建议使用typedef)
#define BOOL int
6.控制条件编译.
带参数的宏
带参数的宏(也称函数式宏)的定义: #define 标识符(x1,x2……,xn) 替换列表
注意:1.在宏的名字和左括号之间必须没有空格。如果有空格,预处理器会认为是在定义一个简单的宏,其中(x1,x2,……,xn)是替换列表的一部分
2.x1,x2,……,xn是标识符(宏的参数)。这些参数可以在替换列表中根据需要出现任意次
当预处理器遇到带参数的宏时,会将宏定义存储起来以后以便后面使用。在后面的程序中,如果任何地方出现了标识符(y1,y2,……,yn)格式的宏调用(其中y1,y2,……,yn是一系列记号),预处理器会使用替代列表替代——使用y1替代x1,y2替代x2,以此类推。如:
#define MA(x,y) ((x)>(y)?(x):(y)) #define IS_EVEN(n) ((n)%2==0)
若出现以下语句:
i=MAX(j+k,m-n); if(IS_EVEN(i)) i++;
则预处理器会将这些行替换为:
i=((i+k)>(m-n)?(j+k):(m-n)); if(((i)%2==0)) i++;
带参数的宏还可以包含空的参数列表,如:
#define getchar() getc(stdin) //<cstdio>中的getchar()
*:使用带参数的宏替代真正的函数的优点:
1.程序可能会稍微快些。使用宏没有函数调用时的各种运行开销
2.宏更通用。与函数的参数不同,宏的参数没有类型。因此,只要预处理后的程序依然是合法的,宏可以接受任何类型的参数。如MAX宏中的两个数的类型可以是int、long、float、double等
*:使用单餐数的宏替代真正旱地忽的缺点:
1.编译后的代码通常会变大,使程序变得更加繁琐
2.宏参数没有类型检查。预处理器不会检查宏参数的类型,也不会进行类型的转换。
3.无法使用一个指针来指向一个宏。
4.宏可能会不止一次的计算它的参数。
带参数的宏不仅适用于模拟函数调用,还经常用作需要重复书写的代码段模式。例如如果在编写程序时厌烦了语句:
printf("%d\n",i);
则我们可以定义如下的宏:
#define PRINT_INT(n) printf("%d\n",n)
此时:
PRINT_INT(i/j); //等价于printf("%d\n",i/j);
(待续……)
以上是关于笔记3:预处理器-宏定义的主要内容,如果未能解决你的问题,请参考以下文章