900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > C语言 带参数宏定义中 # 和 ## 知识点总结 代码分析

C语言 带参数宏定义中 # 和 ## 知识点总结 代码分析

时间:2024-02-08 14:05:13

相关推荐

C语言 带参数宏定义中  # 和 ## 知识点总结 代码分析

目录

一、宏定义中 “#”知识点

1、直接转换字符串,不展开。

2、转换出的结果一定是“字符串”。

二、宏定义中 ## 知识点

1、应用场景

2、“##”的作用是将 左右两边的参数做整体字符串拼接替换

3、经过 ## 替换后的内容必须 有一个 同名的 变量与之对应。

4、 只拼接,不展开。

5、## 操作 动态函数指针 案例代码

一、宏定义中 “#”知识点

#的作用是将“#”后面的宏参数进行字符串转换操作,也就是将#后面的参数 两边加上一对双引号,使其成为字符串。

这里面有几个知识点:

1、直接转换字符串,不展开。

这句话的意思是,带参数宏定义也是宏,而不是普通函数,所以要保留宏的基本特性,也就是全部替换,而不展开。示例代码:

#include <stdio.h>#include <stdlib.h>#define CONVERT(a) #aint main(int argc, char *argv[]) {int a = 6;printf("res:%s\n", CONVERT(a));return 0;}

运行结果:

res:a

2、转换出的结果一定是“字符串”。

代码如下:

#include <stdio.h>#include <stdlib.h>#define CONVERT(a) #aint main(int argc, char *argv[]) {printf("string print:%s\n", CONVERT(6));// 字符串格式打印printf("int print:%d\n", CONVERT(6));// 整型打印return 0;}

运行结果如下:

string print:6int print:4210688

二、宏定义中 ## 知识点

1、应用场景

## 的 应用场景主要是 函数指针的动态绑定,使用该宏参数,可以实现 同类型函数指针 赋值或者引用的 方便操作。这个后面会有代码详细分析。

2、“##”的作用是将 左右两边的参数做整体字符串拼接替换

不管 ## 左右两边是字母还是数字,最终都是作为 一个整体 拼接成一个字符串。代码如下:

#include <stdio.h>#include <stdlib.h>#define FUNC(a) func_##avoid func_1(void){printf("this is func 1.\n");}void func_2(void){printf("this is func 2.\n");}int main(int argc, char *argv[]) {FUNC(1)();FUNC(2)();return 0;}

3、经过 ## 替换后的内容必须 有一个 同名的 变量与之对应。

比如 运行 FUNC(1),必须要保证 有一个 func_1 函数, 同样的 FUNC(2) 对应 func_2函数,如果没有,编译会报错,提示对象未 定义。

4、 只拼接,不展开。

这个类似于 # ,也是原封不动的转换,并不会进一步展开,比如:

int i = 1;FUNC(i)();

尽管 i = 1,但是 FUNC(i) 的结果是 func_i,而不是 func_1.,所以我们不能够使用 ## 的时候,自作聪明的使用变量。

5、## 操作 动态函数指针 案例代码

在 知识点3中,我们提到 不能使用 变量 和 ## 的结合来实现 动态绑定函数指针,那么我们的程序代码就相对不太方便,尤其是我们 想要定义 一系列的 函数,这些函数主题名相同,但是序号不同,那么这个时候,就推荐使用 结构体 数据结构,代码如下所示:

#include <stdio.h>#include <stdlib.h>#define FUNC(a) func_##avoid func_0(void){printf("this is func 0.\n");}void func_1(void){printf("this is func 1.\n");}void func_2(void){printf("this is func 2.\n");}//包含函数 序号、 函数指针的 结构体typedef struct func_t{int id;void (*func)(void);} func_map_t;// 函数结构体 数组static func_map_t g_func_map[3] = {{0, FUNC(0)},{1, FUNC(1)},{2, FUNC(2)},};int main(int argc, char *argv[]) {g_func_map[0].func(); //间接调用 序号对应的 函数。g_func_map[1].func();g_func_map[2].func();return 0;}

这里需要注意的是,我们在定义 上面的 g_func_map 数组 时,需要 在 函数func_0、func_1、func_2之后,这可能是因为编译器先后顺序的原因,如果g_func_map 在这三个函数之前,那么会出现 编译报错信息,显示 这3个函数未定义,可以简单的认为,在定义的时候,数据类型从 前面 查找, 而不是全局查找。

运行结果如下:

this is func 0.this is func 1.this is func 2.

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。