文档章节

【原创】Stringification 在二级宏定义中的使用

摩云飞
 摩云飞
发布于 2013/04/28 13:39
字数 771
阅读 381
收藏 1
点赞 0
评论 0

        最近在研究 Redis-2.6.12 的源码时,重新对一处宏展开的用法进行了梳理,记录如下:

在 zmalloc.h 中有如下定义,
/* Double expansion needed for stringification of macro values. */
#define __xstr(s) __str(s)
#define __str(s) #s
       在注释中出现了一个专有名词“ stringification ”,经查阅,网络上比较认可的翻译是“字符串化”。所以上面双重宏定义的用途为“用于宏值字符串化的双重宏展开 ”。这个概念似乎比较模糊,无法让我深刻理解其用意,幸好有下面的 资料
3.4 Stringification

Sometimes you may want to convert a macro argument into a string constant. Parameters are not replaced inside 
string constants, but you can use the ‘#’ preprocessing operator instead. When a macro parameter is used with 
a leading ‘#’, the preprocessor replaces it with the literal text of the actual argument, converted to a string 
constant. Unlike normal parameter replacement, the argument is not macro-expanded first. This is called stringification.

There is no way to combine an argument with surrounding text and stringify it all together. Instead, you can 
write a series of adjacent string constants and stringified arguments. The preprocessor will replace the 
stringified arguments with string constants. The C compiler will then combine all the adjacent string constants 
into one long string.

Here is an example of a macro definition that uses stringification:

     #define WARN_IF(EXP) \
     do { if (EXP) \
             fprintf (stderr, "Warning: " #EXP "\n"); } \
     while (0)
     WARN_IF (x == 0);
          ==> do { if (x == 0)
                fprintf (stderr, "Warning: " "x == 0" "\n"); } while (0);
The argument for EXP is substituted once, as-is, into the if statement, and once, stringified, into the argument 
to fprintf. If x were a macro, it would be expanded in the if statement, but not in the string.

The do and while (0) are a kludge to make it possible to write WARN_IF (arg);, which the resemblance of WARN_IF 
to a function would make C programmers want to do; see Swallowing the Semicolon.

Stringification in C involves more than putting double-quote characters around the fragment. The preprocessor 
backslash-escapes the quotes surrounding embedded string constants, and all backslashes within string and character 
constants, in order to get a valid C string constant with the proper contents. Thus, stringifying p = "foo\n"; 
results in "p = \"foo\\n\";". However, backslashes that are not inside string or character constants are not 
duplicated: ‘\n’ by itself stringifies to "\n".

All leading and trailing whitespace in text being stringified is ignored. Any sequence of whitespace in the middle 
of the text is converted to a single space in the stringified result. Comments are replaced by whitespace long before
 stringification happens, so they never appear in stringified text.

There is no way to convert a macro argument into a character constant.

If you want to stringify the result of expansion of a macro argument, you have to use two levels of macros.

     #define xstr(s) str(s)
     #define str(s) #s
     #define foo 4
     str (foo)
          ==> "foo"
     xstr (foo)
          ==> xstr (4)
          ==> str (4)
          ==> "4"
s is stringified when it is used in str, so it is not macro-expanded first. But s is an ordinary argument 
to xstr, so it is completely macro-expanded before xstr itself is expanded (see Argument Prescan). Therefore, 
by the time str gets to its argument, it has already been macro-expanded.
      内容有点长,但确实是对  Stringification 作出了全面的解释。其中也对双重宏定义的用法进行了举例说明。针对 xstr(foo) 展开的情况,由于 xstr() 本身是一个符合普通宏展开定义的东东,而 foo 同样是这样的一个东东 ,所以,在对  xstr(foo) 进行宏展开的时,会按照正常的展开顺序进行,即先展开 foo,再展开 xstr 。

      至于采用二级宏定义的好处,当然就是可以更加灵活的对宏展开时的内容进行控制


© 著作权归作者所有

共有 人打赏支持
摩云飞
粉丝 364
博文 352
码字总数 952690
作品 0
徐汇
程序员
【原创】G_STRLOC 宏

研究 MySQL Proxy 源码过程时,经常会看到类似下面这种调试打印: if (0 != networkmysqldconcommandstates_init(con, &p)) {gdebug("%s: ", GSTRLOC);} 其中的 G_STRLOC 是什么呢? 查看 gl...

摩云飞 ⋅ 2013/03/15 ⋅ 3

关于C语言中的连接符的用法 # ## macro stringize

首先面向需求,小工程、代码不多、版本还挺多... 打算用宏控制开关选项、然后通过一长串 if elif ... endif 来控制生成版本号、而且还要根据兼容性跟细小变更做三级版本号.... 所以就需要一个...

卜霞森 ⋅ 2015/09/24 ⋅ 1

iOS学习之UIPickerView控件的关联选择

接上篇iOS学习之UIPickerView控件的简单使用 接着上篇的代码 http://download.csdn.net/detail/totogo2010/4391870 ,我们要实现的效果如下: 当选择左边的一级选项时,左边展示一级选项里含...

totogo2010 ⋅ 2012/06/25 ⋅ 0

EOSIO 智能合约数据库演练

前几天翻译了一篇关于EOS智能合约数据库的内容,今天来演示一下数据库的使用方法。 目录 增 查 改 删 新增 新增内容往往用到构造函数,来进行数据库对象的新增。 .cpp 所有的智能合约都继承自...

tclabs ⋅ 05/17 ⋅ 0

浅析linux中的宏contianer_of

container_of是linux中的一个宏,它的作用是通过结构体中某一成员的地址来获得该成员所在结构体的地址。其定义在include/linux/kernel.h中653行,如下所示: 下面对上述代码进行简单的介绍:...

拾月彷徨 ⋅ 2011/09/26 ⋅ 0

Angular.js v1.5.6 发布

Angular.js v1.5.6 发布了。 Bug 修复: $browser: set the url even if the browser transforms it(743b33ab,#14427, #14499) $compile: properly bind context to linking functions for ......

oschina ⋅ 2016/05/28 ⋅ 2

Qt5 中对 C++11 一些新特性的封装

C++11 是现在的 C++ 标准的名称,C++11 为 C++ 语言带来很多新特性。 而 Qt 4.8 是 Qt 首个在其 API 中开始使用一些新的 C++11 特性的版本,我之前写过一篇博文:C++11 in Qt 4.8 描述了这个...

红薯 ⋅ 2012/06/12 ⋅ 8

程序猿媛三:ExpandableListView二级菜单选择

二级菜单展开选择列表内容 声明:博文为原创,文章内容为,效果展示,思路阐述,及代码片段。 转载请保留原文出处“http://my.oschina.net/gluoyer/blog”,谢谢! 您可以到博客的“友情链接...

花佟林雨月 ⋅ 2013/11/16 ⋅ 0

QT中的元对象系统(二):创建自定义的QT类型

原创文章,转载请注明出处,谢谢! 作者:清林,博客名:飞空静渡 我们在使用QT编程时,难免要定义自己需要的类型,但像QT自己的类型如QSzie、QString之类的,都是可以存储在QViriant中的,并...

长平狐 ⋅ 2013/01/11 ⋅ 0

Objective-C在LLVM 3.1中的新特性

与C和C++不同,Objective-C中不是由一个标准组织控制的,它一开始完全被Stepstone公司掌控,然而现在却被Apple公司取代了。 这种完全被一个公司掌控的模式可以算是一个优点和或者缺点。例如,...

junwong ⋅ 2012/06/10 ⋅ 2

没有更多内容

加载失败,请刷新页面

加载更多

下一页

熊掌号收录比例对于网站原创数据排名的影响[图]

从去年下半年开始,我在写博客了,因为我觉得业余写写博客也还是很不错的,但是从2017年下半年开始,百度已经推出了原创保护功能和熊掌号平台,为此,我也提交了不少以前的老数据,而这些历史...

原创小博客 ⋅ 27分钟前 ⋅ 0

LVM讲解、磁盘故障小案例

LVM LVM就是动态卷管理,可以将多个硬盘和硬盘分区做成一个逻辑卷,并把这个逻辑卷作为一个整体来统一管理,动态对分区进行扩缩空间大小,安全快捷方便管理。 1.新建分区,更改类型为8e 即L...

蛋黄Yolks ⋅ 46分钟前 ⋅ 0

Hadoop Yarn调度器的选择和使用

一、引言 Yarn在Hadoop的生态系统中担任了资源管理和任务调度的角色。在讨论其构造器之前先简单了解一下Yarn的架构。 上图是Yarn的基本架构,其中ResourceManager是整个架构的核心组件,它负...

p柯西 ⋅ 57分钟前 ⋅ 0

uWSGI + Django @ Ubuntu

创建 Django App Project 创建后, 可以看到路径下有一个wsgi.py的问题 uWSGI运行 直接命令行运行 利用如下命令, 可直接访问 uwsgi --http :8080 --wsgi-file dj/wsgi.py 配置文件 & 运行 [u...

袁祾 ⋅ 今天 ⋅ 0

JVM堆的理解

在JVM中,我们经常提到的就是堆了,堆确实很重要,其实,除了堆之外,还有几个重要的模块,看下图: 大 多数情况下,我们并不需要关心JVM的底层,但是如果了解它的话,对于我们系统调优是非常...

不羁之后 ⋅ 昨天 ⋅ 0

推荐:并发情况下:Java HashMap 形成死循环的原因

在淘宝内网里看到同事发了贴说了一个CPU被100%的线上故障,并且这个事发生了很多次,原因是在Java语言在并发情况下使用HashMap造成Race Condition,从而导致死循环。这个事情我4、5年前也经历...

码代码的小司机 ⋅ 昨天 ⋅ 1

聊聊spring cloud gateway的RetryGatewayFilter

序 本文主要研究一下spring cloud gateway的RetryGatewayFilter GatewayAutoConfiguration spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/config/G......

go4it ⋅ 昨天 ⋅ 0

创建新用户和授予MySQL中的权限教程

导读 MySQL是一个开源数据库管理软件,可帮助用户存储,组织和以后检索数据。 它有多种选项来授予特定用户在表和数据库中的细微的权限 - 本教程将简要介绍一些选项。 如何创建新用户 在MySQL...

问题终结者 ⋅ 昨天 ⋅ 0

android -------- 颜色的半透明效果配置

最近有朋友问我 Android 背景颜色的半透明效果配置,我网上看资料,总结了一下, 开发中也是常常遇到的,所以来写篇博客 常用的颜色值格式有: RGB ARGB RRGGBB AARRGGBB 这4种 透明度 透明度...

切切歆语 ⋅ 昨天 ⋅ 0

CentOS开机启动subversion

建立自启动脚本: vim /etc/init.d/subversion 输入如下内容: #!/bin/bash## subversion startup script for the server## chkconfig: 2345 90 10# description: start the subve......

随风而飘 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部