#和##在宏替换中的作用
#include <stdio.h>
#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)
int main()
{
printf("%s/n",h(f(1,2)));
printf("%s/n",g(f(1,2)));
return 0;
}
首先需要了解#和##的意义。
# 将右边的参数做整体的字符串替换。
#define g(a) #a
则g(hello world) à hello world; g(sleep(1)) à sleep(1)
对于#的参数,即便是另一个宏,也不展开,仍然作为字符串字面信息输出。
所以,g(f(1,2)) à f(1,2)
对于h(f(1,2)),由于h(a)是非#或##的普通宏,需要先宏展开其参数a,即展开f(1,2)为12,则h(a) 宏替换为h(12),进而宏替换为g(12), 进而宏替换为12
## 将左右两边的参数做整体的字符串拼接替换。
#define f(a,b) a##b
则f(1,2) à 12, f(i,1) à i1
同#,对于##的参数,即便是另一个宏,也不展开,仍然作为字符串字面信息输出。
此外,有一个限制是,经过##替换后的内容必须能够作为一个合法的变量。
以上f(i,1) à i1中,如果程序中没有i1的定义,或者通过f(1,i)构成1i,则即便是通过了宏替换,也不能编译通过。
--------------------------------------------------------------------------------
日常实践中,##是常用的替换。尤其在通过C的函数指针来模拟动态绑定时大有用处。
下面是从stackoverflow(具体id记不清了)上摘取的一个例子。
struct command
{
char *name;
void (*function) (void);
};
struct command commands[] =
{
{ "quit", quit_command },
{ "help", help_command },
...
};
构造一个这样的commands数组,是为了在后续的设计中,可以通过交互式的字符串输入,来动态地执行相应的函数。字符串自身作为前缀,”_command”作为后缀。
手工构造这样第一个commands数组显得非常冗余,还容易造成不必要的拼写错误。下面来看看这个宏替换版本。
#define COMMAND(NAME) { #NAME, NAME ## _command }
struct command commands[] =
{
COMMAND (quit),
COMMAND (help),
...
};
清晰了很多!
转载于:https://www.cnblogs.com/catgatp/p/8604245.html
#和##在宏替换中的作用相关推荐
- python宏替换_#和##在宏替换中的作用
#include #define f(a,b) a##b #define g(a) #a #define h(a) g(a) int main() { printf("%s/n" ...
- do {...} while (0) 在宏定义中的作用
有篇文章解释很清楚:do {...} while (0) in macros 然后,一位女程序媛把它翻译了一遍,排版清晰,想省力的看这边.do {...} while (0) 在宏定义中的作用
- #define定义标识符——定义宏——替换规则——##的作用——#undef
首先介绍预定义符号 FILE //进行编译的源文件 LINE //文件当前的行号 DATE //文件被编译的日期 TIME //文件被编译的时间 STDC //如果编译器遵循ANSI C,其值为1,否 ...
- 宏定义中#号和##号的使用
在技术群中有人提了一个问题:如何定义一个宏,打印传递过来的参数的地址.这很简单,像下面这样 [objc] view plaincopy #define pl(param) NSLog(@" ...
- 宏定义中的 ## ... __VA_ARGS__
宏定义中的##操作符和... and _ _VA_ARGS_ _ 1.Preprocessor Glue: The ## Operator 预处理连接符:##操作符 Like the # operat ...
- C语言字符串中使用宏替换
1 背景 在定义一个字符串时,希望有一部分内容可以使用宏替换.当尝试使用如下方式来实现时,发现并不能达到目的. #define XXX programmer char str[] = "I ...
- C语言宏定义中#号的作用
C语言宏定义中#号的作用 前言 #号的作用 前言 最近,在阅读uboot的源码过程中,发现了一段宏定义代码: #define U_BOOT_CMD_MKENT_COMPLETE(_name, _max ...
- Java中的宏变量,宏替换详解。
转载自 Java中的宏变量,宏替换详解. 群友在微信群讨论的一个话题,有点意思,特拿出来分享一下. 输出true false 来看下面这段程序,和群友分享的大致一样. public static vo ...
- c程序语言符号的作用,c语言宏定义中的#,##,#@及\符号的作用
1.#(stringizing)字符串化操作符 作用:将宏定义中的传入参数名转换成用一对双引号括起来参数名字符串.其只能用于有传入参数的宏定 义中,且必须置于宏定义体中的参数名前. 如: #def ...
最新文章
- 如何快速定位当前数据库消耗CPU最高的sql语句?
- DKHadoop人力资源大数据解决方案架构
- LruCache缓存处理及异步加载图片类的封装
- android线程栈默认大小,线程的默认最大堆栈大小 - Internet Information Services | Microsoft Docs...
- 《精彩绝伦的CSS》读书笔记(二)
- java map removeall_Java删除Map中元素
- js 高级 call()
- ie6的png24问题
- Angular 导致公司损失数十亿美元!
- linux/work
- c++整人小程序(附源码)
- 配置嵌入式Servlet容器
- 《OpenGL编程指南(原书第9版)》——第3章 3.0OpenGL绘制方式
- ANSYS or Abaqus? 一个过来人的工作感悟
- Python学习_案例for循环嵌套
- Windows 10开启Teredo隧道连接IPV6
- 【编程题】【Scratch三级】2021.06 躲球游戏
- Android使用svg格式图片,并改变图片颜色
- 科普|股东需要对企业债务承担连带责任
- 体育赛事直播系统的实践之路
热门文章
- sql express 无法启动服务_在Windows2012下安装SQL Server 2005无法启动服务的解决办法...
- openssh升级后root_又一root神器停止营业!时至今日你还需要root吗
- LeetCode算法入门- 3Sum -day9
- linux 内存规划,生产场景怎么对linux系统进行合理规划分区?
- oracle数据库sql的执行过程,Oracle体系结构之SQL语句的执行过程
- svg 地图_找地图素材?有这个网站就够了!
- 打开python环境_windows下切换Python运行环境。
- dz论坛连接mysql数据库_dz论坛搬家后连接数据库等教程
- oracle 换字段顺序,修改ORACLE的字段顺序
- .deploy 文件 php,关于php:Heroku deploy自动删除服务器文件?