C语言“#”用法总结
C语言“#”用法总结
0 前言
“#”在C语言中有多种用法,总结有5种:
- “#”用作引用头文件
- “#”用作宏定义
- “#”用作预编译时的警告、错误
- “#”用作将宏定义转换成字符串
- “##”用作连接两个标识符
以下分别详细解释。
1 “#”用作引用头文件
这一作用比较常见,如包含头文件时,使用 #include
;
2 “#”用作宏定义
如 #define, #endif, #ifndef
3 “#”用作预编译时的警告、错误
如 #warning, #error
4 “#”用作将输入转换成字符串
总所周知,宏定义是可以定义字符串的,如下:
#include <stdio.h>
#define STR "test macro to string"
int main(int argc, char** argv)
{
printf("%srn",STR);
return 0;
}
打印如下:
test macro to string
但是在某些场景下,无法直接宏定义字符串,需要宏定义转成字符串。目前有两个应用场景,如有其他应用场景,欢迎大家评论区留言。
4.1 直接将输入转换成字符串
比如,将数字以字符串的形式打印,或者将任意输入以字符串形式打印:
用宏定义 #define STR1(a) #a
实现:
#include <stdio.h>
#define STR1(a) #a //以“#”的形式将输入转换成字符串,必须以宏定义的方式
int main(int argc, char** argv)
{
printf("print string: %srn", STR1(test string));
printf("print string: %srn", STR1(10086));
//printf("print string: %srn", #10086);//必须用上面宏定义的方式,直接加#编译报错!!!
return 0;
}
输出:
test macro to string
print string: test string
print string: 10086
代码第3行,用宏定义的方式将输入转换成字符串,注意,必须用宏定义的方式,直接加#编译报错!
4.2 间接将输入转换成字符串
请大家思考一个问题,上节中,如果将数字10086和字符传test string 定义成宏的形式,然后再用STR(a)去打印会如何?直接上代码:
#include <stdio.h>
#define STR1(a) #a //以“#”的形式将输入转换成字符串,必须以宏定义的方式
#define TEST_NUM 10086
#define TEST_STR "test string"
int main(int argc, char** argv)
{
printf("%d to string: %srn", TEST_NUM, STR1(TEST_NUM));
printf("%s to string: %srn", TEST_STR, STR1(TEST_STR));
return 0;
}
打印如下:
10086 to string: TEST_NUM
test string to string: TEST_STR
由上面结果可见,如果我用宏定义了一个整数或字符串,然后用4.1小节的方式打印宏定义,只能直接将宏定义的名字打出,而不能打印出宏定义定义的内容。我们想要实现将打印“TEST_NUM”就能打印出“10086”字符串的效果,该如何实现呢?
还是看代码:(注意第6行,11、12行)
#include <stdio.h>
#define STR1(a) #a //以“#”的形式将输入转换成字符串,必须以宏定义的方式
#define TEST_NUM 10086
#define TEST_STR "test string"
#define STR2(a) STR1(a) //用二级字符串对的方式实现转换成字符串
int main(int argc, char** argv)
{
printf("%d to string: %srn", TEST_NUM, STR1(TEST_NUM));
printf("%s to string: %srn", TEST_STR, STR1(TEST_STR));
printf("%d to string: %srn", TEST_NUM, STR2(TEST_NUM));
printf("%s to string: %srn", TEST_STR, STR2(TEST_STR));
return 0;
}
运行结果打印如下:
10086 to string: TEST_NUM
test string to string: TEST_STR
10086 to string: 10086
test string to string: "test string"
上述结果实现了我们的预期结果(见11、12行打印)。我们 用第6行实现了该功能 。
注意:宏定义是完全替换,所以第12行的打印将引号也打印了出来。如果第4行宏定义的10086加上括号,同样第11行也会将括号打印出来。
5 “##”用作连接两个标识符
“##”可以用于将两个标识符连接起来,上代码:
#include <stdio.h>
#define CONNECT(a,b) a##b
#define NAME_1 "zhangsan"
#define NAME_2 "lisi"
#define NAME(name) NAME_##name
int main(int argc, char** argv)
{
printf("num: %drn", CONNECT(11,12));
printf("name: %srn", NAME(1));
printf("name: %srn", NAME(2));
return 0;
}
结果打印如下:
num: 1112
name: zhangsan
name: lisi
代码第3行宏定义将两个标识符连接,第9行打印如结果第1行所示,将11和12连接起来变成1112;
第10行和第11行,宏展开后,NAME(1)
变成NAME_##1
,NAME(2)
变成NAME_##2
,由于##的作用是连接作用,所以NAME(1)
就是NAME_1
,打印出来就是“zhangsan”
;同样NAME(2)
就是NAME_2
,打印出来就是“lisi”
。
总结
- “#”用作引用头文件:
#include "xxx.h"
- “#”用作宏定义:
#define, #endif, #ifndef
- “#”用作预编译时的警告、错误:
#warning, #error
- “#”用作将宏定义转换成字符串:
#define STR(a) #a
- “##”用作连接两个标识符:
#defind CONECT(a,b) a##b
欢迎大家评论区留言交流!