笔记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:预处理器-宏定义的主要内容,如果未能解决你的问题,请参考以下文章

宏编程是啥?

c语言的宏定义

预定义宏,C语言预定义的宏详解

C语言宏定义

「Rust笔记」Rust之自定义宏写法

简单区分iphone和ipad的宏定义