C语言的宏
总览图
宏的概念
在C语言中,宏是一种预处理指令(#指令关键字),它提供了一种机制,通过将一个宏名指定成任何需要替换的内容,即#define M m,在程序的编译过程中,预处理阶段预处理器会在源代码中将其替换成在它定义时指定的文本内容(称宏替换、宏展开),即,m替换M。
宏的规则
宏名的命名规则:
宏名亦为标识符,也遵守变量的命名规则,不同的是宏名要求字母全大写。
定义的规则:
宏非语句,因此末尾不加分号;不可嵌套定义宏
处理规则:
在程序的编译过程中,预处理阶段预处理器会在源代码中将其展开。
不同于变量,定义不分配内存。
宏不存在类型,也因此它的参数也是无类型的。
宏定义的形式
- #define 宏名 替换内容
- #define 宏名(参数列表) 替换内容
宏的用法
在程序中会多次使用一些数值常量、字符串常量、表达式或是某些相同的逻辑,因此使用宏可以提高程序的精简度、运行效率、可维护性、可拓展性。
无参数的宏
数值宏
//数组长度
#define MAXLENGTH 20
int arr[MAXLENGTH] = {0};
字符串宏
//文件路径
#define TXTPATH "D:\study\cproject"
字符宏
#define BEGIN {
#define END }
int main()
BEGIN
printf("符号宏!");
return 0;
END
表达式宏
//一天的秒数
#define DAY_MIN 24*60*60
带参数的宏
函数宏
#define MALLOC(type,x) (type*)malloc(sizeof(type)*x)
int *p=MALLOC(int,5);
注意:
1.当我们使用宏的时候,出现了一些奇怪的问题,一般情况下皆为我们没有处理好运算符优先级而导致的问题。
#define SUM(a,b) a+b
int main()
{
int i = 3, j = 2;
int k=i&j;
printf("%d\r\n", k + j);//输出4
printf("%d\r\n", SUM(i&j,j));//输出0 展开为i&j+j &优先级低于+ 则i&(j+j) 非意向结果
return 0;
}
//因此对于函数宏 在定义的时候 对于,每个参数一定要用()扩起来以防止类似错误
//如:#define SUM(a,b) (a)+(b)
2.宏是没有作用域的,即便将其定义于函数内,所有的宏皆是全局可见的,但只对在其定义之后使用的语句才生效
void Max()
{
#define MAX(a,b) (a)>(b)?(a):(b)
}
int main()
{
int i = 3, j = 2;
printf("%d\r\n", MAX(i,j));//输出3
return 0;
}
3.函数宏非函数,也区别于函数调用,函数的调用是会在栈中保留程序当前执行的指令,然后跳到调用函数去执行,执行完该完函数后再返回主调函数,返回到栈里保存的指令的位置继续执行;如同看书一样,看到某个生词,跳到页脚看下注释,完后返回继续阅读。
而宏函数则不存在上述问题,仅仅是在预处理阶段将其展开,即将替换内容嵌入到当前程序,所以不可避免的会占用额外的存储空间。
注销宏
使用#undef注销掉宏,此后该宏名失效。
#define MULTI(a,b) (a)*(b)
#undef MULTI
int main()
{
printf("%d\r\n", MULTI(2, 3));//错误提示无法解析的外部符号 _MULTI
return 0;
}
操作系统提供的宏
可直接使用,如下为日志库当中需要使用的少许宏。
int main()
{
printf("%s\r\n", __FILE__);//输出当前所在的文件 main.c
printf("%d\r\n", __LINE__);//输出当前代码所在的行数 34
printf("%s\r\n", __DATE__);//输出当前的日期 Jan 6 2019
return 0;
}