C语言#define的用法(非常详细,新手必看)
预处理功能是 C语言特有的功能,是 C语言和其他高级语言的区别之一。
预处理程序包含许多有用的功能,如宏定义、条件编译等。使用预处理功能可方便程序的修改、阅读、移植和调试,也可方便实现模块化程序设计。
本节要讲的 #define 命令,功能是定义可替换的宏。宏定义是预处理命令的一种,它提供了一种可以替换源码中的字符串的机制。
C语言中的宏定义,类似于 Word 文档中的替换功能,如下图所示,3.14 用 PI 替换。

图 1 文档中的替换功能
根据宏定义中是否有参数,可以将宏定义分为不带参数的宏定义和带参数的宏定义两种。
宏定义不带参数的一般形式如下:
使用 #define 进行宏定义的好处是,需要改变一个常量时只需改变 #define 命令行,整个程序的常量都会随之改变,大大提高了程序的灵活性。宏名要简单且意义明确,一般习惯用大写字母表示,以便与变量名进行区分。
宏名定义后,其即可成为其他宏名定义中的一部分。例如,下面的代码定义了正方形的边长 SIDE、周长 PERIMETER 及面积 AREA 的值:
宏替换是以字符串代替标识符。因此,如果希望定义一个标准的邀请语,可编写如下代码:
关于不带参数的宏定义有以下几点需要强调:
1) 如果字符串中含有宏名,则不进行替换。例如:
2) 如果字符串长于一行,则可以在该行末尾用反斜杠“\”来表示续行。
3) #define 命令出现在程序中函数的外面,宏名的有效范围为定义命令之后到此源文件结束。
在编写程序时,通常会将所有的 #define 放到文件的开始处或独立的文件中,而不是将它们分散放到整个程序中。
4) 可以用 #undef 命令取消之前宏定义的作用域,例如:
5) 宏定义用于预处理命令,它不同于定义的变量,只用作字符替换,不分配内存空间。
对于带参数的宏定义有以下几点需要强调:
1) 进行宏定义时参数要加括号,如不加括号,则有时结果是正确的,有时结果是错误的。
例如,定义一个宏定义 SUM(x,y),实现参数相加的功能,代码如下:
解决的办法就是在对 SUM(x,y) 进行宏扩展时加上括号:
2) 对带参数的宏的展开,只是用语句中的宏名后面括号内的实参字符串代替 #define 命令行中的形参。
3) 在进行宏定义时,宏名与带参数的括号之间不可以加空格,否则会将空格以后的字符都作为替代字符串的一部分。
4) 在带参数的宏定义中,形参不分配内存单元,因此不必进行类型定义。
预处理程序包含许多有用的功能,如宏定义、条件编译等。使用预处理功能可方便程序的修改、阅读、移植和调试,也可方便实现模块化程序设计。
本节要讲的 #define 命令,功能是定义可替换的宏。宏定义是预处理命令的一种,它提供了一种可以替换源码中的字符串的机制。
C语言中的宏定义,类似于 Word 文档中的替换功能,如下图所示,3.14 用 PI 替换。

图 1 文档中的替换功能
根据宏定义中是否有参数,可以将宏定义分为不带参数的宏定义和带参数的宏定义两种。
C语言不带参数的宏定义
宏定义命令 #define 用来定义一个标识符和一个字符串,就是用标识符来替代字符串。宏定义相当于给指定的字符串起一个别名。宏定义不带参数的一般形式如下:
#define 宏名 字符序列有以下几点说明:
- #:表示这是一条预处理命令。
- 宏名:一个标识符,必须符合 C语言标识符的规定。
- 字符序列:可以是常数、表达式、格式字符串等。
例如:注意,宏定义语句不是C语句,不需要在行末加分号。
#define PI 3.14159该语句的作用是用 PI 替代 3.14159,在程序执行前的预处理阶段,每当在源程序中遇到 PI 就自动用 3.14159 代替。
使用 #define 进行宏定义的好处是,需要改变一个常量时只需改变 #define 命令行,整个程序的常量都会随之改变,大大提高了程序的灵活性。宏名要简单且意义明确,一般习惯用大写字母表示,以便与变量名进行区分。
宏名定义后,其即可成为其他宏名定义中的一部分。例如,下面的代码定义了正方形的边长 SIDE、周长 PERIMETER 及面积 AREA 的值:
#define SIDE 6 #define PERIMETER 4*SIDE #define AREA SIDE*SIDE
宏替换是以字符串代替标识符。因此,如果希望定义一个标准的邀请语,可编写如下代码:
#define STANDARD "Come on baby, join us." printf(STANDARD);编译程序遇到标识符 STANDARD 时,就用“You are welcome to join us.”替换。
关于不带参数的宏定义有以下几点需要强调:
1) 如果字符串中含有宏名,则不进行替换。例如:
#include<stdio.h> #define TEST " Come on baby, join us." int main() { char exp[30] = "This TEST is not that TEST"; /*定义字符数组并赋初值*/ printf("%s\n", exp); }输出结果为:
This TEST is not that TEST
可以看到,输出结果中的 TEST 并没有用“Come on baby, join us.”替换,因此如果字符串中含有宏名(这里的宏名是 TEST),则不进行替换。2) 如果字符串长于一行,则可以在该行末尾用反斜杠“\”来表示续行。
3) #define 命令出现在程序中函数的外面,宏名的有效范围为定义命令之后到此源文件结束。
在编写程序时,通常会将所有的 #define 放到文件的开始处或独立的文件中,而不是将它们分散放到整个程序中。
4) 可以用 #undef 命令取消之前宏定义的作用域,例如:
#include<stdio.h> #define TEST " Come on baby, join us." void main() { printf(TEST); #undef TEST }
5) 宏定义用于预处理命令,它不同于定义的变量,只用作字符替换,不分配内存空间。
C语言带参数的宏定义
带参数的宏定义不只是进行简单的字符串替换,还要进行参数替换。其一般形式如下:#define 宏名(参数表) 字符序列例如,定义一个带参数的宏,实现的功能是比较 15 和 9 这两个数值,并且返回最小值。具体代码如下:
#include<stdio.h> /*包含头文件*/ #define MIX(x,y) (x<y?x:y) /*定义一个宏*/ int main() /*主函数main()*/ { int x = 15, y = 9; /*定义变量*/ printf("x,y为:\n"); /*提示输出*/ printf("%d,%d\n", x, y); /*输出*/ printf("the min number is:%d\n", MIX(x, y)); /*宏定义调用*/ return 0; /*程序结束*/ }运行结果为:
x,y为:
15,9
the min number is:9
对于带参数的宏定义有以下几点需要强调:
1) 进行宏定义时参数要加括号,如不加括号,则有时结果是正确的,有时结果是错误的。
例如,定义一个宏定义 SUM(x,y),实现参数相加的功能,代码如下:
#define SUM(x,y) x+y在参数加括号的情况下调用 SUM(x,y),可以正确地输出结果;在参数不加括号的情况下调用 SUM(x,y),则输出的结果是错误的。比如说:
5*SUM(x,y)则会被扩展为:
5*x+y而本意是希望得到:
5*(x+y)
解决的办法就是在对 SUM(x,y) 进行宏扩展时加上括号:
#define SUM(x,y) (x+y)这样就能避免这种错误发生。
2) 对带参数的宏的展开,只是用语句中的宏名后面括号内的实参字符串代替 #define 命令行中的形参。
3) 在进行宏定义时,宏名与带参数的括号之间不可以加空格,否则会将空格以后的字符都作为替代字符串的一部分。
4) 在带参数的宏定义中,形参不分配内存单元,因此不必进行类型定义。