#define宏的一些用法
首先让我们来查看这个预处理指令更为正式的描述:
#define name stuff
有了这条指令以后,每当有符号 name出现在这条指令的后面时,预处理器就会把它替换成stuff。
我们常常使用这种技巧来为一个数值命名一个符号,实际替换并不仅限于字面值常量
这里有几个例子:
#define CASE break;case
#define DEBUG_PRINT printf( "这是一个调试!/n" )
从上面的两个例子我们也可以看出define指令的强大,我们甚至可以通过使用它来替换一段代码段,可以类似于函数调用一样来使用它,但是它和函数调用的区别还是非常大的,稍后将继续描述两者的区别。
#define 允许把参数替换到文本中,这种实现通常称为宏或定义宏例如:
#define SQUARE(x) x*x
在程序中SQUARE(5)将会被替换成5*5,但是这里会有一个问题,如果在程序中输入SQUARE(6-1),会被替换成什么呢?在使用编译器编译后允许发现输出的结果为-1,并不是想象的25,这是因为SQUARE(6-1)在编译时被替换成了6-1*6-1,注意并没有加括号,所以才会出现前面的结果,要想解决这个问题,就要修改一下前面的语句:
#define SQUARE(x) (x)*(x)
这样SQUARE(6-1)就会被替换成(6-1)*(6-1)这样就会达到我们预想的效果了。我们再来看一个例子:
#define ADD(X) (x)+(x)
如果在程序中10*ADD(5)又将会输出什么值呢?实际上并没有输出我们想象的100,而是输出了55,我们再来分析一下替换后的语句,在程序中10*ADD(5)将会被替换成10*(5)+(5),因此输出55,这可能并不是你所期望的结果,所以这个宏业需要修改:
#define ADD(x) ((x)+(x))
这个宏才是我们的最终版本,所有带参数的宏都用过使用这种格式来定义。这样减减少程序出错了可能性。
下面是一个有趣的宏:
#define repeat do
#define until(x) while( !(x) )
这两个宏创建了一种“新”的循环,其工作过程类似于其他语言中的repeat/until循环。它按照下面的语句进行工作:
repeat
{
statements
}until( i >= 10 );
预处理器将替换成下面的语句
do
{
statements
}while( !(i >= 0) );
这个例子可以说明我们可以使用#define创建一套宏,用一种看上去很象其他语言的方式编写C程序,这是一个诱惑,可以模仿其他的一门编程语言。
宏还有另外一种用法:
#define PRINT(FORMAT,VALUE) printf("The value is "FORMAT"/n", VALUE)
在程序中可以这样使用这个宏:
PRINT( "%d", 45 );
这个语句的输出结果是:The value is 45
这个技巧利用了临近字符串自动连接的特性使我们很容易把一个字符串分成几段。当然这中技巧只有当字符串常量作为宏参数给出时才能使用。
第二个技巧是使用预处理器把一个宏参数转换为一个字符串:
#define PRINT(FORMAT,VALUE) printf("The value "#VALUE" is "FORMAT"/n", VALUE)
在程序中这样使用这个宏:
PRINT(%d, x+3);
这里加入x的值为23,则这条语句的输出结果是:The value x+3 is 26