预处理器之宏的使用

来源:互联网 发布:博森瑞大数据dba培训 编辑:程序博客网 时间:2024/06/06 05:04

        我们知道C程序在编译过程之前,C语言预处理器首先对程序代码作了了必要的转换处理。 宏在C程序中是非常有用的,比如我们可以通过修改宏定义来修改在程序中出现的所有实例。同时通过宏定义还可以免去函数调用带来的重大系统开销。

虽然宏定义非常有用,但是宏定义也是非常容易出错的。主要表现为以下几点:

1、 不能忽视宏定义中 的空格

比如在下面的宏定义中

       #define f  (x)  ((x)-1) 因为在f和(x)之间有一个空格,所以这个宏定义实际代表的是f 代表(x) ((x)-1),这和我们预想的f  (x)代表((x)-1)相去甚远。

     ****这里需要特别注意的是,虽然在宏定义的时候空格不能忽视,但是当我们在程序中用到宏定义时,空格却是可以忽略的,比如我们的宏定义中#define f(x)  x+3;在程序中我们可以用f(x)来调用该宏,这时候是没有任何错误的。

2、宏并不是函数

因为宏从表面上看其行为与函数非常相似,我们有时候会把他们视为完全相同。然而情况却并非如此。

比如我们定义一个宏 #define max(a,b)    a>b?a:b;  但是当我们计算max(x-z,y-z)时,宏展开后的结果却和我们预想的相去甚远,展开为 x-z>y-z?x-z:y-z;  显然这不是我们想要的结果。因此在进行宏定义的时候我们最好都把每个参数用大括号括起来。同样整个结果表达式也应该用括号括起来,以防止当宏用于一个更大一些的表达式中可能出现的错误问题。

是不是这样的宏就没有任何问题了,当然不是!!!!!!!!!!!在宏调用中,如果一个操作数在两处被调用,就会被求值两次,比如我们定义的宏#define max(a,b)    a>b?a:b;  在进行宏调用时,max(x++,y++);中的x和y都用可能被++两次,解决这种问题的方法有两个,要么不使用宏调用,将宏改为函数,要么宏调用中的参数没有副作用。

3、宏并不是类型定义

很多编程者都喜欢用宏来定义一种数据类型,比如 :

#define FOOTYPE struct foo *

       FOOTYPE a;

       FOOTYPE b,c;

编程者本来的意图是将b,c都定义为指向结构的指针,而事实上将第二个声明扩展开为

struct foo * a,b;

这个语句中a被定义为一个指向结构的指针,而b却被定义为一个结构(而不是指针);