现在的位置: 首页 > 综合 > 正文

C语言基础之宏定义##连接符和#符

2018年11月05日 ⁄ 综合 ⁄ 共 1564字 ⁄ 字号 评论关闭

一、#

在函数式宏定义中,#运算符用于创建字符串,简单说就是在它引用的宏变量的左右各加上一个双引号。#运算符后面应该跟一个形参(中间可以有空格或Tab),

如定义好#define STRING(x) #x之后,下面二条语句就等价。
       char *pChar = "hello";
       char *pChar = STRING(hello);
还有一个#@是加单引号(Charizing Operator)
#define makechar(x)  #@x
       char ch = makechar(b);与char ch = 'b';等价。

#define STR(s) # s STR(hello world)
用cpp命令预处理之后是"hello␣world",自动用"号把实参括起来成为一个字符串,并且实参中的连续多个空白字符被替换成一个空格。
 

二、#@
在函数式宏定义中,#@运算符用于创建一个字符,例如:
#define makechar(x)  #@x
a = makechar(b);
预处理之后是
a = 'b';

三、##
在宏定义中可以用##运算符把前后两个预处理Token连接成一个预处理Token,和#运算符不同,##运算符不仅限于函数式宏定义,变量式宏定义也可以用。例如:
#define CONCAT(a, b) a##b
CONCAT(con, cat)
预处理之后是concat。再比如,要定义一个宏展开成两个#号,可以这样定义:
#define HASH_HASH # ## #

中间的##是运算符,宏展开时前后两个#号被这个运算符连接在一起。注意中间的两个空格是不可少的,如果写成####,会被划分成##和##两个Token,而根据定义##运算符用于连接前后两个预处理Token,不能出现在宏定义的开头或末尾,所以会报错。

但有小问题要注意,宏中遇到#或##时就不会再展开宏中嵌套的宏了。什么意思了?比如使用char *pChar = STRING(__FILE__);虽然__FILE__本身也是一个宏,但编译器不会展开它,所以pChar将指向"__FILE__"而不是你要想的形如"D:\XXX.cpp"的源文件名称。因此要加一个中间转换宏,先将__FILE__解析成"D:\XXX.cpp"字符串。
定义如下所示二个宏:

例1:

#define _STRING(x) #x
#define STRING(x) _STRING(x)
再调用下面语句将输出带""的源文件路径
       char* pChar = STRING(__FILE__);
       printf("%s %s\n", pChar, __FILE__);
可以比较下STRING(__FILE__)与__FILE__的不同,前将带双引号,后一个没有双引号。

例2:
有了上面的基础后再来看示例1
#define WIDEN2(x) L ## x
#define WIDEN(x) WIDEN2(x)
#define __WFILE__ WIDEN(__FILE__)
wchar_t *pwsz = __WFILE__;

第一个宏中的L是将ANSI字符串转化成unicode字符串。如:wchar_t *pStr = L"hello";
再来看wchar_t *pwsz = __WFILE__;
__WFILE__被首先展开成WIDEN(__FILE__),再展开成WIDEN2("__FILE__表示的字符串"),再拼接成 L"__FILE__表示的字符串" 即L"D:\XXX.cpp" 从而得到unicode字符串并取字符串地址赋值给pwsz指针。

参考博文:http://www.360doc.com/content/08/0515/10/26398_1260866.shtml

http://www.cnblogs.com/morewindows/archive/2011/08/18/2144112.html

抱歉!评论已关闭.