#define宏定义在C语言中是什么意思(非常详细)
宏定义是预处理命令的一种,它提供了一种可以替换源代码中字符串的机制。
简单来说,宏定义指令 #define 用来定义一个标识符和一个字符串,以这个标识符来代表这个字符串,在程序中每次遇到该标识符时就用所定义的字符串替换它。
宏定义的作用相当于给指定的字符串起了一个别名。
注意,C语言并没有规定 #define 必须写在函数外面,只是规定这条命令必须单独占一个完整的逻辑行。其作用范围是 #define 出现的位置到所在源文件结束,或到相应的 #undef 预处理指令处。如果需要 #define 预处理命令仅在某个函数内有效,完全可以把它写在函数内。
例如,下面宏定义的作用是在程序中用 PI 替代 3.14159:
使用 #define 进行宏定义的好处是:当需要改变一个常量时,只需改变 #define 命令行,整个程序的常量都会改变,大大提高了程序的灵活性。
宏名定义后,即可成为其他宏名定义中的一部分。例如,下面代码定义了正方形的边长 SIDE、周长 PERIMETER 及面积 AREA 的值。
前面强调过,宏替换是以字符串代替标识符。因此,可定义一个标准的邀请语:
关于不带参数的宏定义,有以下几点需要注意。
1) 如果在字符串中出现宏名,则不进行替换。例如:
2) 如果字符串多于一行,可在行末用反斜杠“\”进行续行。
3) #define命令出现函数外时,宏名的有效范围为定义命令之后到此源文件结束。
注意,通常会将所有 #define 放到文件开始处或独立的文件中,而不是将它们分散到整个程序中。
4) 可以用 #undef 命令终止宏定义的作用域,例如:
5) 宏定义是一种预处理命令,不同于变量定义,它只做字符替换,而不分配内存空间。
【实例 1】要求对两个数实现乘法和加法混合运算,代码如下:
对于带参数的宏定义,有以下几点需要注意:
1) 宏定义时,参数要加括号。如不加括号,则结果可能是正确的,也可能是错误的。
实例 1 中,如果宏定义语句改为:
2) 宏扩展必须使用括号来保护表达式中优先级低的操作符,以确保调用时能达到预期效果。
实例 1 中,如果宏扩展外没有加括号,则调用 5*MIX(x, y),会被扩展为 5*(a)*(b)+(b),而本意是希望得到 5*((a)*(b)+(b)),显然出现了错误。
3) 对带参数的宏的展开,只是用宏名后括号内的实参字符串代替 #define 命令行中的形参。
4) 宏定义时,宏名与带参数的括号之间不要加空格,否则会将空格以后的字符都作为替代字符串的一部分。
5) 在带参宏定义中,形式参数不分配内存单元,因此不必做类型定义。
简单来说,宏定义指令 #define 用来定义一个标识符和一个字符串,以这个标识符来代表这个字符串,在程序中每次遇到该标识符时就用所定义的字符串替换它。
宏定义的作用相当于给指定的字符串起了一个别名。
C语言不带参数的宏定义
首先来讲解不带参数的宏定义,其一般形式如下:#define 宏名 字符串
- “#”表示这是一条预处理命令;
- 宏名是一个标识符,必须符合 C语言中对标识符的限定。宏名要简单且意义明确,一般习惯用大写字母表示,以便与变量名相区别;
- 字符串可以是常数、表达式、格式字符串等。
注意,C语言并没有规定 #define 必须写在函数外面,只是规定这条命令必须单独占一个完整的逻辑行。其作用范围是 #define 出现的位置到所在源文件结束,或到相应的 #undef 预处理指令处。如果需要 #define 预处理命令仅在某个函数内有效,完全可以把它写在函数内。
例如,下面宏定义的作用是在程序中用 PI 替代 3.14159:
#define PI 3.14159编译预处理时,每当在源程序中遇到 PI,就自动用 3.14159 代替。注意,宏定义不是 C 语句,不需要在行末加分号。
使用 #define 进行宏定义的好处是:当需要改变一个常量时,只需改变 #define 命令行,整个程序的常量都会改变,大大提高了程序的灵活性。
宏名定义后,即可成为其他宏名定义中的一部分。例如,下面代码定义了正方形的边长 SIDE、周长 PERIMETER 及面积 AREA 的值。
#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."替换。
关于不带参数的宏定义,有以下几点需要注意。
1) 如果在字符串中出现宏名,则不进行替换。例如:
#include<stdio.h> #define TEST "this is an example" main() { char exp[30]="This TEST is not that TEST"; /* 定义字符数组并赋初值 */ printf("%s\n",exp); }运行结果为:
This TEST is not that TEST
可见,字符串中的两处 TEST 并没有用"this is an example"替换。2) 如果字符串多于一行,可在行末用反斜杠“\”进行续行。
3) #define命令出现函数外时,宏名的有效范围为定义命令之后到此源文件结束。
注意,通常会将所有 #define 放到文件开始处或独立的文件中,而不是将它们分散到整个程序中。
4) 可以用 #undef 命令终止宏定义的作用域,例如:
#include<stdio.h> #define TEST "this is an example" main() { printf(TEST); #undef TEST }运行结果为:
this is an example
5) 宏定义是一种预处理命令,不同于变量定义,它只做字符替换,而不分配内存空间。
C语言带参数的宏定义
带参数的宏定义,不仅要进行字符串替换,还要进行参数替换。其一般形式如下:#define 宏名(参数表)字符串
【实例 1】要求对两个数实现乘法和加法混合运算,代码如下:
#include<stdio.h> #define MIX(a,b) ((a)*(b)+(b)) /*宏定义,求两个数的混合运算*/ 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)); /*宏定义调用*/ }程序运行结果为:
x,y:
5,9
the min number is:54
printf("the min number is: %d",((a)*(b)+(b)));用宏替换代替实在的函数,好处是可以提升代码速度(不再存在函数调用),代价是由于重复编码,增加了程序长度。
对于带参数的宏定义,有以下几点需要注意:
1) 宏定义时,参数要加括号。如不加括号,则结果可能是正确的,也可能是错误的。
实例 1 中,如果宏定义语句改为:
#define MIX(a,b) (a*b+b) /*宏定义,求两个数的混合运算*/则 main() 函数中,x=10,y=9 时调用 MIX(x, y),可以输出正确结果 99;x=10,y=3+4 时调用 MIX(x, y),执行情况为 (10*3+4+3+4),将输出错误结果为 41。因此,宏定义时一定要给参数加上括号。
2) 宏扩展必须使用括号来保护表达式中优先级低的操作符,以确保调用时能达到预期效果。
实例 1 中,如果宏扩展外没有加括号,则调用 5*MIX(x, y),会被扩展为 5*(a)*(b)+(b),而本意是希望得到 5*((a)*(b)+(b)),显然出现了错误。
3) 对带参数的宏的展开,只是用宏名后括号内的实参字符串代替 #define 命令行中的形参。
4) 宏定义时,宏名与带参数的括号之间不要加空格,否则会将空格以后的字符都作为替代字符串的一部分。
5) 在带参宏定义中,形式参数不分配内存单元,因此不必做类型定义。