精品-清华大学C语言课件 第16章01 宏定义
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include<stdio.h> #define TEST "this is an example" void main() { char exp[30]="This TEST is not that TEST";/*定义字符数组并赋初值*/ printf("%s\n",exp); }
该段代码输入结果如图16.1所示:
#include<stdio.h> #define TEST "this is an example" main() { printf(TEST); #undef TEST }
宏定义用于预处理命令,它不同于定义的变量,只作字符替换,不分配内存空间。
带参数的宏定义
带参数的宏定义不是简单的字符串替换,还要进行参数替换。一般形式如下: #define 宏名(参数表)字符串 【例16.1】 对两个数实现乘法加法混合运算。
#include<stdio.h> #define MIX(a,b) ((a)*(b)+(b))/*宏定义求两个数的混合运算*/ void main() { int x=5,y=9; printf("x,y:\n"); printf("%d,%d\n",x,y); printf("the min number is:%d\n",MIX(x,y)); /*宏定义调用*/ }
运行程序,显示效果如图16.4所示。 图16.4 用宏定义实现值互换
Thank you
5*(a)*(b)+(b)
而本意是希望得到:
5*((a)*(b)+(b))
解决的办法就是上面说的宏扩展时加上括号就能避免这种错误发生。
对带参数的宏的展开只是将语句中的宏名后面括号内的实参字符串代替#define命令行中的形参。 在宏定义时,在宏名与带参数的括号之间不可以加空格,否则将空格以后的字符都作为替代字符串的 一部分。
程序运行结果如图16.2所示:
图16.2 混合运算
当编译该程序时,由MIX(a,b)定义的表达式被替换,x和y用作操作数,即printf()语句被替换后取如 下形式:
printf("the min number is: %d",((a)*(b)+(b)));
用宏替换实在的函数的一个好处是宏替换增加了代码的速度,因为不存在函数调用。但增加速度也有 代价:由于重复编码而增加了程序长度。
int AREA;/*定义整形变量,存储平行四边形面积*/ AREA=A * H;/*计算平行四边形面积*/ printf("AREA = %d\n",AREA);/*输出面积值*/
}运行程序,显示效果如图16.3所示。
图16.3 不带参数的宏定义求平行四边形面积
实例2 使用宏定义实现数组值的互换
对于带参数的宏定义有以下几点需要强调:
宏定义时参数要加括号,如不加括号,有时结果是正确的,有时结果便是错误的,那么什么时候是正 确的,什么时候是错误的,下面具体说下:
如实例16.1当参数x=10,y=9时,在参数不加括号的情况下调用MIX(x,y),可以正确的输出结果;当 x=10,y=3+4时,在参数不加括号的情况下调用MIX(x,y),则输出的结果是错误的,因为此时调用的 MIX(x,y)执行情况如下:
在带参宏定义中,形式参数不分配内存单元,因此不wenku.baidu.com作类型定义。
实例1 不带参数的宏定义求平行 四边形面积
利用不带参数的宏定义求平行四边形的面积,平行四边形的面积=底边×高。将平行四边形的底边 和高设置为宏的形式(一般宏名都是大写字母,以便与其他的操作符区别)。
#include <stdio.h> #define A 8/*定义宏,设置底边的长度*/ #define H 6/*定义宏,设置高的长度*/ void main() {
宏定义
本讲大纲
1.不带参数的宏定义 2.带参数的宏定义 实例1 不带参数的宏定义求平行四边形面积 实例2 使用宏定义实现数组值的互换
不带参数的宏定义
宏定义指令#define用来定义一个标识符和一个字符串,以这个标识符来代表这个字符串,在程序 中每次遇到该标识符时就用所定义的字符串替换它。它的作用相当于给指定的字符串起一个别名。 不带参数的宏定义一般形式如下:
使用#define进行宏定义的好处是需要改变一个常量的时候只需改变#define命令行,整个程序的常 量都会改变,大大的提高了程序的灵活性。
宏名要简单且意义明确,一般习惯用大写字母表示以便与变量名相区别。 注意: 宏定义不是C语句,不需要在行末加分号。
宏名定义后,即可成为其它宏名定义中的一部分。例如,下面代码定义了正方形的边长SIDE、周长 PERIMETER及面积AREA的值。
(10*3+4+3+4);
此时计算出的结果是41,而实际上希望得出的结果是77,所以为了避免出现上面这种情况,在进行宏 定义时要在参数外面要加上括号。
宏扩展必须使用括号,来保护表达式中低优先级的操作符,以便确保调用时达到想要的效果。
如果例16.1宏扩展外没有加括号,则调用:
5*MIX(x,y)
则会被扩展为:
#define SIDE 5 #define PERIMETER 4*SIDE #define AREA SIDE*SIDE
前面强调过宏替换是以串代替标识符这点。因此,如果希望定义一个标准的邀请语,可编写如下 代码:
#define STANDARD "You are welcome to join us." printf(STANDARD);
编译程序遇到标识符STANDARD时,就用"You are welcome to join us."替换。 对于编译程序,printf()语句如下形式是等效的:
printf("possible use of ‘i’ before definition in function main");
关于不带参数的宏定义有以下几点要强调下: 如果在串中含有宏名,则不进行替换。 例如:
试定义一个带参的宏swap(a,b),以实现两个整数之间的交换,并利用它将一维数组a和b的值进行 交换。
#include <stdio.h> #define swap(a,b) {int c;c=a;a=b;b=c;}/*定义一个带参的宏swap*/ int main() { int i, j, a[10], b[10];/*定义数组及变量为基本整型*/ printf("请输入一个数组a:\n"); for (i = 0; i < 10; i++) scanf("%d", &a[i]);/*输入一组数据存到数组a中*/ printf("请输入一个数组b:\n"); for (j = 0; j < 10; j++) scanf("%d", &b[j]);/*输入一组数据存到数组b中*/ printf("\n数组a是:\n"); for (i = 0; i < 10; i++) printf("%d,", a[i]);/*输出数组a中的内容*/ printf("\n数组b是:\n"); for (j = 0; j < 10; j++) printf("%d,", b[j]);/*输出数组b中的内容*/ for (i = 0; i < 10; i++) swap(a[i], b[i]);/*实现数组a与数组b对应值互换*/ printf("\n现在数组a是:\n"); for (i = 0; i < 10; i++) printf("%d,", a[i]);/*输出互换后数组a中的内容*/ printf("\n现在数组b是:\n"); for (j = 0; j < 10; j++) printf("%d,", b[j]);/*输出互换后数组b中的内容*/ puts(""); return 0; }
#define 宏名 字符串
“#”表示这是一条预处理命令。 宏名是一个标识符,必须符合C语言标识符的规定。 字符串这里可以是常数、表达式、格式字符串等。 例如:
#define PI 3.14159
它的作用是在该程序中用PI替代3.14159,在编译预处理时,每当在源程序中遇到PI就自动用 3.14159代替。
注意上面程序字符串中的TEST并没有用“this is an example”来替换,所以说如果串中含有宏名, 则不进行替换。
如果串长于一行,可以在该行末尾用一反斜杠“\”续行。 #define命令出现在程序中函数的外面,宏名的有效范围为定义命令之后到此源文件结束。 注意: 在编写程序时通常将所有的#define放到文件的开始处或独立的文件中,而不是将它们分散到整个程序 中。 可以用#undef命令终止宏定义的作用域。
该段代码输入结果如图16.1所示:
#include<stdio.h> #define TEST "this is an example" main() { printf(TEST); #undef TEST }
宏定义用于预处理命令,它不同于定义的变量,只作字符替换,不分配内存空间。
带参数的宏定义
带参数的宏定义不是简单的字符串替换,还要进行参数替换。一般形式如下: #define 宏名(参数表)字符串 【例16.1】 对两个数实现乘法加法混合运算。
#include<stdio.h> #define MIX(a,b) ((a)*(b)+(b))/*宏定义求两个数的混合运算*/ void main() { int x=5,y=9; printf("x,y:\n"); printf("%d,%d\n",x,y); printf("the min number is:%d\n",MIX(x,y)); /*宏定义调用*/ }
运行程序,显示效果如图16.4所示。 图16.4 用宏定义实现值互换
Thank you
5*(a)*(b)+(b)
而本意是希望得到:
5*((a)*(b)+(b))
解决的办法就是上面说的宏扩展时加上括号就能避免这种错误发生。
对带参数的宏的展开只是将语句中的宏名后面括号内的实参字符串代替#define命令行中的形参。 在宏定义时,在宏名与带参数的括号之间不可以加空格,否则将空格以后的字符都作为替代字符串的 一部分。
程序运行结果如图16.2所示:
图16.2 混合运算
当编译该程序时,由MIX(a,b)定义的表达式被替换,x和y用作操作数,即printf()语句被替换后取如 下形式:
printf("the min number is: %d",((a)*(b)+(b)));
用宏替换实在的函数的一个好处是宏替换增加了代码的速度,因为不存在函数调用。但增加速度也有 代价:由于重复编码而增加了程序长度。
int AREA;/*定义整形变量,存储平行四边形面积*/ AREA=A * H;/*计算平行四边形面积*/ printf("AREA = %d\n",AREA);/*输出面积值*/
}运行程序,显示效果如图16.3所示。
图16.3 不带参数的宏定义求平行四边形面积
实例2 使用宏定义实现数组值的互换
对于带参数的宏定义有以下几点需要强调:
宏定义时参数要加括号,如不加括号,有时结果是正确的,有时结果便是错误的,那么什么时候是正 确的,什么时候是错误的,下面具体说下:
如实例16.1当参数x=10,y=9时,在参数不加括号的情况下调用MIX(x,y),可以正确的输出结果;当 x=10,y=3+4时,在参数不加括号的情况下调用MIX(x,y),则输出的结果是错误的,因为此时调用的 MIX(x,y)执行情况如下:
在带参宏定义中,形式参数不分配内存单元,因此不wenku.baidu.com作类型定义。
实例1 不带参数的宏定义求平行 四边形面积
利用不带参数的宏定义求平行四边形的面积,平行四边形的面积=底边×高。将平行四边形的底边 和高设置为宏的形式(一般宏名都是大写字母,以便与其他的操作符区别)。
#include <stdio.h> #define A 8/*定义宏,设置底边的长度*/ #define H 6/*定义宏,设置高的长度*/ void main() {
宏定义
本讲大纲
1.不带参数的宏定义 2.带参数的宏定义 实例1 不带参数的宏定义求平行四边形面积 实例2 使用宏定义实现数组值的互换
不带参数的宏定义
宏定义指令#define用来定义一个标识符和一个字符串,以这个标识符来代表这个字符串,在程序 中每次遇到该标识符时就用所定义的字符串替换它。它的作用相当于给指定的字符串起一个别名。 不带参数的宏定义一般形式如下:
使用#define进行宏定义的好处是需要改变一个常量的时候只需改变#define命令行,整个程序的常 量都会改变,大大的提高了程序的灵活性。
宏名要简单且意义明确,一般习惯用大写字母表示以便与变量名相区别。 注意: 宏定义不是C语句,不需要在行末加分号。
宏名定义后,即可成为其它宏名定义中的一部分。例如,下面代码定义了正方形的边长SIDE、周长 PERIMETER及面积AREA的值。
(10*3+4+3+4);
此时计算出的结果是41,而实际上希望得出的结果是77,所以为了避免出现上面这种情况,在进行宏 定义时要在参数外面要加上括号。
宏扩展必须使用括号,来保护表达式中低优先级的操作符,以便确保调用时达到想要的效果。
如果例16.1宏扩展外没有加括号,则调用:
5*MIX(x,y)
则会被扩展为:
#define SIDE 5 #define PERIMETER 4*SIDE #define AREA SIDE*SIDE
前面强调过宏替换是以串代替标识符这点。因此,如果希望定义一个标准的邀请语,可编写如下 代码:
#define STANDARD "You are welcome to join us." printf(STANDARD);
编译程序遇到标识符STANDARD时,就用"You are welcome to join us."替换。 对于编译程序,printf()语句如下形式是等效的:
printf("possible use of ‘i’ before definition in function main");
关于不带参数的宏定义有以下几点要强调下: 如果在串中含有宏名,则不进行替换。 例如:
试定义一个带参的宏swap(a,b),以实现两个整数之间的交换,并利用它将一维数组a和b的值进行 交换。
#include <stdio.h> #define swap(a,b) {int c;c=a;a=b;b=c;}/*定义一个带参的宏swap*/ int main() { int i, j, a[10], b[10];/*定义数组及变量为基本整型*/ printf("请输入一个数组a:\n"); for (i = 0; i < 10; i++) scanf("%d", &a[i]);/*输入一组数据存到数组a中*/ printf("请输入一个数组b:\n"); for (j = 0; j < 10; j++) scanf("%d", &b[j]);/*输入一组数据存到数组b中*/ printf("\n数组a是:\n"); for (i = 0; i < 10; i++) printf("%d,", a[i]);/*输出数组a中的内容*/ printf("\n数组b是:\n"); for (j = 0; j < 10; j++) printf("%d,", b[j]);/*输出数组b中的内容*/ for (i = 0; i < 10; i++) swap(a[i], b[i]);/*实现数组a与数组b对应值互换*/ printf("\n现在数组a是:\n"); for (i = 0; i < 10; i++) printf("%d,", a[i]);/*输出互换后数组a中的内容*/ printf("\n现在数组b是:\n"); for (j = 0; j < 10; j++) printf("%d,", b[j]);/*输出互换后数组b中的内容*/ puts(""); return 0; }
#define 宏名 字符串
“#”表示这是一条预处理命令。 宏名是一个标识符,必须符合C语言标识符的规定。 字符串这里可以是常数、表达式、格式字符串等。 例如:
#define PI 3.14159
它的作用是在该程序中用PI替代3.14159,在编译预处理时,每当在源程序中遇到PI就自动用 3.14159代替。
注意上面程序字符串中的TEST并没有用“this is an example”来替换,所以说如果串中含有宏名, 则不进行替换。
如果串长于一行,可以在该行末尾用一反斜杠“\”续行。 #define命令出现在程序中函数的外面,宏名的有效范围为定义命令之后到此源文件结束。 注意: 在编写程序时通常将所有的#define放到文件的开始处或独立的文件中,而不是将它们分散到整个程序 中。 可以用#undef命令终止宏定义的作用域。