目录

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

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:6
int 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.

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

  1. 宏定义有无参数宏定义和带参数宏定义两种

    宏定义有无参数宏定义和带参数宏定义两种. 无参数的宏定义的一般形式为 # define 标识符 字符序列 其中# define之后的标识符称为宏定义名(简称宏名),要求宏名与字符序列之间用空格符分隔. ...

  2. c语言宏定义可变参数,C语言可变参数宏定义方法

    http://blog.csdn.net/skyflying2012/article/details/38436711 2014 在GNU C中,宏可以接受可变数目的参数,就象函数一样,例如: 1 2 ...

  3. c 语言 宏 可变 参数,C语言 如何在宏定义中使用可变参数

    有一个记录日志的函数,想用宏定义进行包装,简化调用方法,但是xlc报如下的错误:void _log(const int level, char* file, int line, const char* ...

  4. C语言带参宏定义和函数的区别

    带参数的宏和函数区别: 宏展开仅仅是字符串的替换,不会对表达式进行计算:宏在编译之前就被处理掉了,它没有机会参与编译,也不会占用内存.而函数是一段可以重复使用的代码,会被编译,会给它分配内存,每次调用 ...

  5. [C语言编程入门]带参数宏定义

    问题描述 定义一个带参的宏,使两个参数的值互换,并写出程序,输入两个数作为使用宏时的实参.输出已交换后的两个值. 解决方案: #include<stdio.h> #define swap( ...

  6. [编程入门]带参数宏定义练习:定义一个带参的宏,使两个参数的值互换,并写出程序,输入两个数作为使用宏时的实参。输出已交换后的两个值。

    #include<bits/stdc++.h> #define fun(a,b) t=a;a=b;b=t; using namespace std;int main() {int a,b, ...

  7. mysql宏参数_C语言带参数的宏定义

    C语言允许宏带有参数.在宏定义中的参数称为"形式参数",在宏调用中的参数称为"实际参数",这点和函数有些类似. 对带参数的宏,在展开过程中不仅要进行字符串替换, ...

  8. 【C语言】宏定义和带参宏定义

    宏定义是在编程中经常使用的一个模块,其优点在于当写的代码量比较大的时候方便修改检查,可以做到改一变"百". 一.宏定义 宏定义是用宏名来表示一个字符串,在宏展开时又以该字符串取代宏 ...

  9. 巧用c语言宏定义实现自动注释调试代码,C语言宏定义中的特殊用法

    C宏定义中的特殊用法 在分析一些C源码时,经常会遇到各种宏定义操作,本文即总结一下C语言宏定义中常见的预定义宏.调试宏:宏的条件编译用法及特殊的宏关键字用法. #undef 限定宏的作用域 一般来讲宏 ...

最新文章

  1. 关于Android开源库分享平台,(GitClub)微信小程序的开发体验
  2. jenkins需安装插件总结
  3. Spark编程指南笔记
  4. 5 Android数据存储 任务二 应用程序数据文件夹里的文件读写 ,
  5. 【数据竞赛】Kaggle秘技,用Sigmoid函数做回归问题!
  6. java 1.8签名apk_给Android的APK程序签名和重新签名的方法
  7. Leetcode 565. Array Nesting
  8. 大数据自学——Spark
  9. Python:Python程序设计思维、计算生态、用户体验、程序设计模式
  10. Java集合Collection接口中的常用方法演示
  11. 2021年南阳市五中高考成绩查询,南阳市“赫赫有名”的五大高中,2020年高考成绩一目了然!...
  12. ueditor+asp.net异步提交,可以实现了,嘿嘿
  13. lbochs模拟器最新版_bochs模拟器最新版下载
  14. 圆锥曲线之用齐次法求解直线过定点问题
  15. V-rep机器人仿真软件使用的学习笔记-续
  16. 有关于fprintf()函数的用法
  17. 荣耀MagicOS 7.0正式发布;快手科技2022年第三季度收入同比增长12.9% | 美通企业日报...
  18. 2022年下半年信息系统项目管理师下午真题及答案解析
  19. Unity出IOS包报错记 -1
  20. 分享个龙门神途脚本辅助工具,相当于一个云端的安卓模拟器

热门文章

  1. 登录注册与Cookie
  2. BIND的进阶二:视图,日志,转发,子域的授权
  3. Ubuntu系统下安装ZEC币服务
  4. React中的高优先级任务插队机制
  5. 历史事件词条1000条
  6. Oracle收集统计信息
  7. DirectUI,标准界面的又一次挑战!
  8. Spring Boot使用Servlet居然也可以实现长轮询,敲了5年代码,我居然不知道 - 第413篇
  9. 【20171015】【软工】结对项目
  10. [excel]删除excel中隐藏的双引号(用的WPS)