2.2 宏定义

宏定义又称为宏替换,简称宏。它是在预处理阶段用预先定义的字符串替代标识符的过程。其定义的一般形式为:


define 标识符 字符串


宏定义中的标识符都采用大写,这是编程中一种约定俗成的习惯。在了解如何使用宏定义之前,我们先来了解使用宏的过程中需要注意的几个要点。

宏替换不做语法检查,所以在使用的时候要格外小心。

宏替换通常在文件开头部分,写在函数的花括号外边,作用域为其后的程序,直到用#undef命令终止宏定义的作用域。

不要在字符串中使用宏,如果宏名出现在字符串中,那么将按字符串进行处理。

2.2.1 简单宏替换

简单宏替换在编程中通常用来定义常量。如在编程中多次用到同一个常量时,我们可以为该常量定义一个宏名,以便只修改赋值语句中的值就可以实现对程序中所有该宏名出现处的值进行修改。同时,使用宏名还可以使程序的可读性得以提升。

1.简单宏定义的优点

(1)减少不必要的修改,提升程序的可预读性

如涉及圆周率,我们可以采用如下的宏定义来实现:


define PI 3.1415


如果需要修改圆周率的精度,只需要在宏定义中修改就可以实现了,而不必到程序中逐个修改所有用到的圆周率。同时,采用宏的方式比直接采用数值的方式使程序更容易理解,可读性增强了。

(2)提升代码的可移植性

使用宏定义不仅仅可以增强代码的可读性,还可以提高代码的可移植性,如:


define INT_SIZE sizeof(int)


在某些编译环境下,sizeof(int)的值可能为4,但是这并不代表在所有的环境下它的运行结果都为4,也可能为2或8,所以针对此类情况,为了提高代码的可移植性,在编程时最好采用宏定义的方式。

2.使用简单宏定义要注意的问题

在宏定义中,有一点是我们不得不注意的,那就是宏定义仅仅是简单宏替换,它不负责任何计算顺序,这就可能不小心带来难以查找的错误,所以在使用宏定义计算表达式的值时要格外小心,如:


define A 12+12

define B 10+10


当定义了以上的宏定义之后,如果在代码中执行AB,那么在预处理阶段,AB将被扩展为12+12*10+10,从扩展后的表达式可知得到的结果并不是我们所期望的值,所以要想得到正确的结果,在宏定义的时候可以采用以下方式。


define A(12+12)

define B(10+10)


在宏定义中也可以通过#undef来设定宏名的作用域,我们可以通过以下代码来具体看看#undef的使用。


include<stdio.h>

define N 9

void main()

{

int i,a[N];

for(i=0;i<N;i++)

{

a[i]=i;

printf("a[%d]=%d\t",i,a[i]);

if((i+1)%3==0)

printf("\n");

}

//#undef N

printf("%d\n",N);

return;

}


运行结果为:


a[0]=0 a[1]=1 a[2]=2

a[3]=3 a[4]=4 a[5]=5

a[6]=6 a[7]=7 a[8]=8

9


由于通过#undef可以设定宏名的作用域,当在以上代码中注释掉“#undef N”时,接下来的打印语句能够正常打印出N的值;而没有注释掉“#undef N”时,由于此时N的作用域结束,所以接下来在打印语句部分就会出现“error C2065:'N':undeclared identifier”错误,提示N没有定义。由此可以看出,在编程时可以用#undef来设定定义的宏的作用域。