我也要学C语言-第十二章:编译预处理——带参数的宏

Posted on 2011-05-29 16:50  dodolook  阅读(2411)  评论(15编辑  收藏  举报

带参数的宏

  为了进一步扩大宏的应用范围,在定义宏的时候,还可以带参数

一般形式:#define 标识符(参数表) 字符串

  带参数宏的作用:在编译预处理时,将源程序中所有标识符替换成字符串,并且将字符串中的参数用实际使用的参数替换。

例子:#define S(a,b) (a*b)/2

  上面这个例子则源程序中如果使用了S(3,4),在编译预处理时就会将其替换为(3*4)/2

代码事例:

#include <stdio.h>
#define PI 3.14159
#define L(r) 2*PI*(r)
#define S(r) PI*(r)*(r)

void main()
{
int i =5;

printf(
"%f", S(i));
}

我们来看下此段程序的编译预处理后的结果:

void main()
{
int i =5;

printf(
"%f", 3.14159*(i)*(i));
}

嘿嘿!就是这样子的了!宏其实就是针对我们的源文件做了1个查找替换的工作。

带参宏与函数

  大家是不是发现了一个有趣的问题,带参宏是不是和函数很想象啊!嘿嘿!仔细一瞧,真的好像啊!那么我们现在就来分析下带参宏和函数。

  效率:带参宏比函数效率高,因为,宏是编译之后把代码嵌进去了,而函数调用需要很多的步骤(比如保存现场,恢复现场等操作),但是宏生存的文件体积大,因为,替换一次宏就需要生存一个相应的代码段,而函数不会,函数只会有1次代码量。例如:

#include <stdio.h>
#define PI 3.14159
#define L(r) 2*PI*(r)
#define S(r) PI*(r)*(r)

void main()
{
int i =5;

printf(
"%f", S(i));
  printf("%f", S(i));
  printf("%f", S(i));
  printf("%f", S(i));
  printf("%f", S(i));




}

我们多次调用宏,我们去看下编译器做了什么工作:

void main()
{
int i =5;

printf(
"%f", 3.14159*(i)*(i));
printf(
"%f", 3.14159*(i)*(i));
printf(
"%f", 3.14159*(i)*(i));
printf(
"%f", 3.14159*(i)*(i));
printf(
"%f", 3.14159*(i)*(i));
}

可见编译器为我们生成了5段代码。

我们再看看:

#include <stdio.h>
#define PI 3.14159
#define L(r) 2*PI*(r)
#define S(r) PI*(r)*(r)

#define go(i) printf("%f", S(i))




void main()
{
int i =5;

go(i);
go(i);
go(i);
go(i);
go(i);
}

编译器生成了以下代码:

void main()
{
int i =5;

printf(
"%f", 3.14159*(i)*(i));
printf(
"%f", 3.14159*(i)*(i));
printf(
"%f", 3.14159*(i)*(i));
printf(
"%f", 3.14159*(i)*(i));
printf(
"%f", 3.14159*(i)*(i));
}

这样的结果是:可执行代码的体积增加了,但是效率提高了。原因是没有了函数调用的消耗。

带参宏注意的问题:宏名和参数之间不能有空格,否者空格后面的所有字符序列都作为替换的字符串;带参数的宏展开时,只做简单的字符和参数的替换,不进行任何的计算机操作。所以一般定义宏的时候,一定要加上小括号。例如2*PI*(r).如果没有小括号,在某些时候就会得出错误的结果。例如:#define L(r) 2*PI*r 如果源程序是L(2+3),那么编译预处理后的结果为:2*3.14159*2+3;例如:

#include <stdio.h>

#define L(r) 2*r
#define S(r) r*r

void main()
{
printf(
"%d", S(6-4));
}

这段代码,我们会想到输出的结果为4.但是真正的输出结果呢,为-22.为什么会这样呢?!我们看看编译预处理后的代码:

void main()
{
printf(
"%d", 6-4*6-4);
}

嘿嘿!大家知道原因了吧!所以一定养成写小括号的习惯哦!

带参宏也可以当化妆品用:

  嘿嘿!我们看以下代码:

#include <stdio.h>

#define IF(r) if(r)
#define THEN {
#define ELSE }else{
#define ENDIF }

#define PRINT(S) printf(s);

#define DIM
#define INT int

void main()
{
DIM INT a
=6;
IF(a
%2==0) THEN
PRINT(
"偶数\n")
ELSE
PRINT(
"奇数\n")
ENDIF
}

哈哈!现在看起来这个C程序是不是怪模怪样的啊!然后我们看这段代码的编译预处理后的代码:

void main()
{
int a =6;
if(a%2==0) {
printf(s);
}
else{
printf(s);
}
}

学到现在,编译预处理还有,文件包含和条件编译的章节!加油啊!!!