预编译(预处理或者预处理器处理)
预定义符号
#include<stdio.h>
#include<stdlib.h>
#define DEBUG_PRINT() \
printf("file:%s line:%d date:%s time:%s\n",\
__FILE__,__LINE__,__DATE__,__TIME__)
int main()
{
DEBUG_PRINT();
//printf("file:%s line:%d date:%s time:%s\n",__FILE__,__LINE__,__DATE__,__TIME__);
system("color 03");
system("pause");
return 0;
}
define定义的宏和标识符
define定义的标识符
#define reg register
#define DO_FOREVER for(;;)
#define CASE break;case
define定义的宏
注意:
1).不应在宏定义的尾部加上分号(如果在宏定义的尾部添加分号会产生歧义,若在if ... else语句中更加明显)
2)
.
在定义宏时宏名的后面不要添加空格,在使用时允许添加
3).在定义宏时尽量给变量添加圆括号,避免宏的副作用
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
//带有副作用的宏
#define MAX(X,Y)((X)>(Y)?(X):(Y))
int main()
{
//int a=10,b=20;
//int ret=MAX(a++,b++); //((a++)>(b++)?(a++):(b++)) ((10)>(20)?(X):(21))
//printf("a=%d b=%d ret=%d\n",a,b,ret); //11 22 21
int a=20,b=10;
int ret=MAX(a++,b++); //((a++)>(b++)?(a++):(b++)) ((20)>(10)?(21):(Y))
printf("a=%d b=%d ret=%d\n",a,b,ret); //22 11 21
system("pause");
return 0;
}
宏和函数的优缺点
1).在代码长度角度上,因为宏是直接替换所以若宏较长会增加代码长度
2).在执行速度上,宏较函数快,因为函数存在调用/返回时的额外开销
3).在参数求值方面,define定义的宏可能会具有副作用会导致修改变量最后的值,而函数即使调用多次也不会修改变量原来的值
4).在参数类型方面,宏与类型无关,所以宏是可以传参数的而函数不行在C中函数是不可以传类型的
5).在是否可调试方面,宏不可调试,函数可调试
宏可以传类型的检测,实现malloc(动态开辟内存的函数)
#include<stdio.h>
#include<stdlib.h>
#define MALLOC(COUNT,TYPE)\
(TYPE *)alloc(COUNT*sizeof(TYPE))
void *alloc(int sz) //宏可以传类型,函数不可以传类型
{
void *p=malloc(sz);
if(p == NULL)
{
printf("out of memory\n");
exit(EXIT_FAILURE);
}
return p;
}
int main()
{
int i=0;
int *p=MALLOC(10,int);
for(i=0;i<10;i++)
{
*(p+i)=i;
}
for(i=0;i<10;i++)
{
printf("%d ",*(p+i));
}
free(p);
system("pause");
return 0;
}
#和##号
#:
使宏的参数不会被展开,转化为对应的字符串
##
将两个标识符连接起来;允许宏从分离的文本片中创建标识符
#include<stdio.h>
#include<stdlib.h>
#define M 100
#define PRINT(FORMAT,VALUE)\
printf("the value of "#VALUE" is "FORMAT,VALUE)
#define CAT(STR1,STR2)\
STR1##STR2
int main()
{
int aabb=100;
char *str="i love you.";
PRINT("%s",str); //the value of str is i love you.
printf("\n%d\n",CAT(aa,bb));
system("color 03");
system("pause");
return 0;
}
Thans