#和##
#运算符:
#运算符将宏的⼀个参数转换为字符串字⾯量。它仅允许出现在带参数的宏的替换列表中。
#运算符所执⾏的操作可以理解为“字符串化”。
举例:
当我们有⼀个变量 int a = 10; 的时候,我们想打印出: the value of a is 10 .时,我们会采取哪些方法?
第一种调用函数:
void printf(int n)
{
printf("the value of n is %d\n",n);
}
int main()
{
int a =10;
Print(a);
return 0;
}
结果:
很显然并不能使用调用函数打出我们想要的目标。
第二种宏
#define Print(n, format) printf(" the value of n is "format" \n ",n)
int main()
{
int a =10;
Print(a,"%d");
return 0;
}
结果:
很显然,宏也不能完全完成我们所需要的目标。
所以在这两个代码的基础上,就产生了#运算符,#运算符和##运算符其实并不是C语言中的运算符,它们两个实际上都是预编译中为了引起预编译时,编译器的注意而产生的运算符,只服务于预编译。
使用#运算符:
#define Print(n, format) printf(" the value of " #n " is %d" , n);
使用#将所需要被预编译代替和发现的字符显示出来,且在这里我们使用了字符串的多段输出。
##运算符:
- ## 可以把位于它两边的符号合成⼀个符号,它允许宏定义从分离的⽂本⽚段创建标识符。
- ## 被称 为记号粘合 这样的连接必须产⽣⼀个合法的标识符。否则其结果就是未定义的。
关于##运算符的用法,其实最常见的就是在使用#define定义一个调用函数模板的时候。
如下所示:
在这里呢,我们设置了一个宏,用这个宏来进行一个类似于函数调用的模板。
函数对比:
int intmax(int x, int y)
{
return x>y?x:y;
}
代码和上图进行对比,就会发现,#define定义了一个函数,利用了宏的特性。
将上图进入预编译中进行对比:
- 通过以上,我们可以明白这个函数的意图,(类型) 类型最大值(类型参数1,类型参数2)
- {return 参数1>参数2?参数1:参数2}
- (类型) 类型最大值(类型参数1,类型参数2)就下就像是一个函数调用的写法,最前面的(类型)相当于是函数调用的返回值,类型最大值(类型参数1,类型参数2)这个就相当于一个调用函数。
- 如上诉,再这当中##表示的就是一个连接作用,因为typemax不可能只替换type,所以需要##进行粘合,以此来脱离替换,但是再编译器中,二者又是黏合的,前面一段可替换的样子。