前言
本人学生党,辣鸡一个,还望包涵
正文
一、宏定义的基本使用方法
宏定义对于学过c语言的人来说应该并不陌生,其实说白了就是#define
,但是对于初学者来说,用法一般只有这样
// 定义一个常量
#define CONST "value"
但是实际上这个宏定义还可以定义一些“函数”,比如说下面的
// 定义一个加法的宏
#define add(num1, num2) (num1 + num2)
这句话的意思其实是当你在写add(5, 6)
的时候,5被当作num1,6被当作num2,然后对宏展开的内容进行替换,也就是替换成(5+6)
。编译器会在进行预处理的时候完成这个替换。
二、使用代码块完成宏定义
但是如果说在这个定义中要使用多个语句或者说其他的变量怎么办呢?我们可以使用代码块来完成这些操作。
// 代码块是{}
// 定义一个交换两个变量值的宏
#define exchange(num1, num2) {int c; c=num1; num1=num2; num2=c;}
在代码块中定义的变量会在程序离开该块的时候失效,这样的话这个变量c就不会影响到宏定义以外的代码内容。
三、行连接符''
我们可以看到,上面的宏定义因为把所有的语句都写在了同一行,看起来十分臃肿,那我们有没有什么办法把它分成几行呢?肯定是有的,我们用''连接符可以链接两行之间的内容
// 还是上面的那个交换
#define exchange(num1, num2) \
{ \
int c; \
c=num1; \
num1=num2; \
num2=c; \
}
但是要注意的是。''符号同一行的后面不能再有任何的字符。最经常的错误就是''后面加多了空格或者是制表符,这样也会导致编译错误。
四、连接符'##'和字符串化操作符'#'
有的时候,我们想要连接两个字符串,这个时候我们可以使用符号##,它会帮我们把左右宏参数连接起来。而#号会给后面的内容的左右加上双引号,也就是变成字符串
我们先举一个关于##符号的例子
// 指数宏
#define _POWER(_BASE_, _EXPONENT_) (int)(_BASE_##e##_EXPONENT_)
#define POWER(_BASE_, _EXPONENT_) _POWER(_BASE_, _EXPONENT_)
我们可以用宏实现把两个数字转换成一个指数。但是我们注意到,我这里好像画蛇添足的加多了一个宏,这个是为什么呢?因为凡是加了#或者##的宏是不会进行二次解析的。比如说下面的:
#define A 1
#define B 2
_POWER(A, B); // 这里会被替换成 (int)(AeB);
POWER(A, B); // 这里先会被替换成 _POWER(1, 2); 然后变成 (int)(1e2);
所以说我们在使用的时候需要进行多一步转换。
最后再举一个#符号使用的例子,其实这个我使用的不是很多,所以只能是给一个最简单的例子:
// 将一个数字转换称为字符串
#define a 90 // 在这里a是(int)90
#define _STR(_STRING_) #_STRING_
#define STR(_STRING_) _STR(_STRING_)
printf("The number is %s.\n", STR(a)); // 这里会把a先转换成90再转换成“90”
这些宏有时候可以帮助我们完成重要的操作,所以还是很有用的。