1、#define定义标识符
语法:
#define name stuff
例子:
#define MAX 1000
#define reg register //为 register这个关键字,创建一个简短的名字
#define do_forever for(;; ) //用更形象的符号来替换一种实现
#define CASE break;case //在写case语句的时候自动把 break写上。
// 如果定义的 stuff过长,可以分成几行写,除了最后一行外,每行的后面都加一个反斜杠(续行符)。
#define DEBUG_PRINT printf("file:%s\tline:%d\t
date:%s\ttime:%s\n" ,
__FILE__,__LINE__,
__DATE__,__TIME__)
注:在define后面不要加;号,否则很容易出错。
例如:在下面的场景中会报错:
#define MAX 1000;
if(condition)
max = MAX; //相当于max=1000;; 两个分号会报错
else
max = 0;
2、#define定义宏
#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏(define macro)。
下面是宏的申明方式:
#define name( parament-list ) stuff
其中的 parament-list 是一个由逗号隔开的符号表,它们可能出现在stuff中。
注意:
- 参数列表的左括号必须与name紧邻。
- 如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分。
如:
#define SQUARE(x) x*x
当我们传入参数为5时,SQUARE( 5 )将会替换成为5 * 5,而当我们传入的参数为5+1,很多人会认为结果为36,但是程序运行结果为11。因为运算符有优先级,因此5+1*5+1会先运算1 * 5,在加上5和1,最终结果为11。
所以应该定义为:
#define SQUARE(x) ((x)*(x))
总结:用于对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏时由于参数中的操作符或邻近操作符之间不可预料的相互作用。
3、#define替换规则
在程序中扩展#define定义符号和宏时,需要涉及几个步骤。
1、在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先被替换。
2、替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值替换。
3、最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上述处理过程。
注意:
1、宏参数和#define 定义中可以出现其他#define定义的变量。但是对于宏,不能出现递归。(宏的宏体内再写了一个宏是不行的)但是在使用宏的时候嵌套使用是可以的。
2、当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。(如果定义#define MAX 10即如果在打印中printf(“MAX = %d”,MAX); 中双引号内的MAX是不能够用宏来替换的,最终打印的结果为MAX = 10)
4、#和##
#的作用:
首先我们看看这样的代码:
char* p = "hello ""world\n";
printf("hello"," world\n");
printf("%s", p);
两行输出结果是一样的,都是hello world。我们发现字符串是有自动连接的特点的。
在宏的使用中,它有一个作用是能够将一个字符串变为传递给宏的一个参数的变量符号。例:
#define PRINT(n) printf("the value of "#n" is %d\n",n)
int main()
{
int a = 10;
PRINT(a);
int b = 20;
PRINT(b);
}
##的作用:
##可以把位于它两边的符号合成一个符号。它允许宏定义从分离的文本片段创建标识符。
举一个简单的例子:
#define cat(X,Y) X##Y
int main()
{
printf("%d",cat(1, 2));
return 0;
}