首页 理论教育C语言宏定义示例(第3版)

C语言宏定义示例(第3版)

【摘要】:使用带参数宏定义时,除了前面提到的使用宏定义预处理的注意事项外,还要注意下面几点:①带参宏定义中,宏名和形参表之间不能有空格出现。②带参宏定义中,形式参数不分配内存单元,因此不必作类型定义。而带参数的宏对实参表达式不作计算直接照原样代换,只是进行简单的替换。③带参数宏的形式参数与函数中的形式参数不同,它没有确定的数据类型。带参数宏调用替换问题的理解示例。

带参数宏定义除了进行字符串替换外,还通过参数的代入实现更加复杂的宏代换功能,带参数宏定义的一般形式为:

#define 标识符(形参表) 表达式样式字符串

宏调用的格式为:

标识符(实参表)

带参数的宏调用时一般分为两个步骤。例如,对于宏定义:#define S(a,b)a*b进行宏调用的形式为T=S(3,2);,第一步将宏换为T=a*b;,第二步将实参代入换为T=3*2;。

使用带参数宏定义时,除了前面提到的使用宏定义预处理的注意事项外,还要注意下面几点:

①带参宏定义中,宏名和形参表之间不能有空格出现。

如:#define S(a,b) a*b

如果误写为:#define S (a,b) a*b,则将被认为是无参宏定义,宏名为S,字符串为(a,b) a*b。

②带参宏定义中,形式参数不分配内存单元,因此不必作类型定义。(www.chuimin.cn)

③在宏定义中的形参是标识符,而宏调用中的实参可以是表达式。为了避免当实参是表达式时的替换错误,定义时应将用于替换字符串中的所有形参用圆括号括起来。请比较并区别下面两种形式。

在C程序中使用带参数宏代换时,特别需要注意宏代换和函数调用的区别:

①函数调用时,先求出实参表达式的值,然后代入形式参数。而带参数的宏对实参表达式不作计算直接照原样代换,只是进行简单的替换。

②函数调用是在程序运行时处理的,因为形参要分配临时的存储单元。而带参数宏的展开则是在编译前进行的,在展开时并不分配内存单元,不进行值的传递处理,也没有返回值的概念。

③带参数宏的形式参数与函数中的形式参数不同,它没有确定的数据类型。在宏调用时随着代入的实际参数数据类型的不同,其运算结果的类型随之而变。

在程序设计时,采用宏定义还是函数需要根据情况而定,有关函数的部分已经在前面章节介绍过,与函数比较,宏定义的好处是宏替换是在编译阶段进行的,不占运行时间。同时它也有缺点,宏定义在预处理时原地进行替换展开,一般会增加代码的长度;此外,宏调用时并没有参数类型的检查,有可能引起不可预料的程序设计错误。

【例9.3】 带参数宏调用替换问题的理解示例。

在阅读理解上面程序时最容易得到的错误结果是:t=3000。事实上,宏替换后得到的表达式为:t=Min(a+b,c+d)*1000;→t=(a+b)<(c+d)?(a+b):(c+d)*1000;,从预处理完成的语句可以看出,在条件表达式中,当(a+b)<(c+d)的结果是1(非0)时,表达式最后的1000与应该取得的值毫无关系。程序运行的正确结果为:t=3。