预处理器可以简化某些工作:
第一个原因:某些特定的数量,路径,字符串可能在程序中出现很多次。可以定义一个宏,例如把数值定义成显式常量。这样修改的时候只要改一个地方就可以了。另外预处理器可以很容易地将所有常量定义在一起,找到 常量就变得很容易。
第二个原因:函数调用会带来系统开销,那么可以用 宏定义一个程序块,使得它看上去像一个函数却没有函数调用的开销。
注意,宏只是对文本起作用 。
宏定义中的空格不能忽视
#define f (x) ((x)-1) //这里要注意多了个空格,整个宏定义就不一样了
#define f(x) ((x)-1)
宏不是函数
为了预防引起与优先级有关的问题,最好在宏定义中把每个参数都括起来。
#define abs(x) x>0?x:-x
#define abs(x) (x)>0?(x):(-x)
当输入a-b时,abs(a-b)
对于第一个宏,a-b?a-b:-a-b
对于第二个宏 ,(a-b)?(a-b):-(a-b)
可以看出给参数加上括号,可以防止用于更大一些表达式中可能出现的问题。
另外,在宏的参数中混合了递增运算符之后,会使得代码岌岌可危。
建议不要混合递增递减运算符。
所以还是不要让宏去做函数的工作,容易出错;
宏不是语句
有时候我们会试图定义宏的行为和语句类似,但这样做的实际困难往往令人吃惊。
所以也不建议这么去定义
宏不是类型定义
尽量使用类型定义,typedef,这更加通用一些。typedef定义了一个新的类型
typedef struct foo FOOTYPE
#define FOOTYPE struct foo
#define T1 struct foo *
typedef struct foo *T2;
T1 a,b;
T2 a,b;
第一个声明被扩展为struct foo * a,b; //a被定义为指向结构的指针 ,b被定义为一个结构;
第二个声明则是定义了两个指向结构体的指针;