首先,推荐大家一本书《C与指针》,第14章讲宏讲的非常的详细。

       如:

【面试简答题(详谈)】宏与函数的区别_宏与函数的区别

 

 

宏可以非常频繁地用于执行简单的计算,比如在两个表达式中寻找其中较大(或较小)的一个:

#define MAX( a, b )     ( (a) > (b) ? (a) : (b) )

为什么不用函数来完成这个任务呢?有两个原因:

     1.用于调用和从函数返回的代码很可能比实际执行这个小型计算工作的代码更大,

所以使用宏比使用函数在程序的规模和速度更胜一筹。

     2.但是更重要的是,函数的参数必须申明为一种特定的类型,所以它只能在类型合适的表达式上使用。

反之,上面的宏可以用于×××、长×××、单浮点型、双浮点型以及其他任何可以使用>操作符比较值大小的类型。

换句话说:

     宏是类型无关的。


     和函数相比,使用宏的不利之处在于每次使用宏时,一份宏定义代码的拷贝将插入到程序中,除非宏非常短,否则使用宏可能会大幅度增加程序的长度。

     还有一些任务根本无法使用函数实现。让我们仔细观察下面的代码:

     #define MALLOC( n,    type)      \

       ( ( type *) malloc ( (n) * sizeof( type ) ) )


        int *pi = MALLOC( 25, int );


这个宏的第二个参数是一种类型,它无法作为函数参数进行传递。

这个宏替换完成之后:

int *pi = ( ( int *) malloc ( (25) * sizeof( int ) ) );

 

 

带副作用的宏参数

     当宏参数在宏定义中出现次数超过一次时,如果这个参数具有副作用,那么当你使用这个宏时就可能出现危险,导致不可预料的结果。副作用就是在表达式求值时出现的永久性效果。例如,下面表达式

   x + 1;

可以执行几百次,他每次获得结果都是一样的,这个表达式不具有副作用。但是

  x ++;    

就有副作用:它增加x的值。当这个表达式下一次执行时,他将产生一个不同的结果。MAX宏可以证明具有副作用的参数所引起的问题。

#define MAX( a, b )  ( (a) > ( b) ? (a ) : (b) )

        int x = 5;

        int y = 8;

        int z = MAX( x++, y++);

        printf("x = %d, y = %d, z = %d\n" , x, y, z );


这里较小的值计算了一次,但是较大的值却计算了两次。


副作用并不仅限于修改变量的值,getchar()也会产生副作用。调用这个函数将”消耗“输入的一个字符。

 

#define 宏的行为和真正的函数相比存在一些不同的地方。



由于有了这些不同之处,所以让程序员知道一个标识符究竟是一个宏还是一个函数式非常重要的。不幸的是,使用宏的语法和使用函数的语法是完全一样的,所以语言本身并不能区分这个两者。

【面试简答题(详谈)】宏与函数的区别_宏与函数的区别_02