#define 中的“#”和“##”
来源:互联网 发布:红旗linux界面图 编辑:程序博客网 时间:2024/04/30 15:54
【转载自】:http://blog.163.com/y845766643@126/blog/static/17104630220113289280333/
define f(a,b) a##b
define d(a) #a
define s(a) d(a)
void main( void )
{
puts(d(f(a,b)));
puts(s(f(a,b)));
}
输出结果:
f(a,b)
ab
分析: ##把两个符号连起来
#a指把a当成符号,就是把#后面的看成字符串
和 ## 操作符是和#define宏使用的. 使用# 使在#后的首个参数返回为一个带引号的字符串. 例如, 命令
#define to_string( s ) # s
将会使编译器把以下命令
cout < < to_string( Hello World! ) < < endl;
理解为
cout < < “Hello World!” < < endl;
使用##连结##前后的内容. 例如, 命令
#define concatenate( x, y ) x ## y
…
int xy = 10;
…
将会使编译器把
cout < < concatenate( x, y ) < < endl;
解释为
cout < < xy < < endl;
理所当然,将会在标准输出处显示’10’.
puts(d(f(a,b))); —-> 因为d宏中的参数是另外一个宏,且带##,所以作为参数的宏不展开,相当于
puts(#f(a,b));—–>puts(“f(a,b)”);
puts(s(f(a,b))); —-> 因为s宏中的参数是另外一个宏,但不带##,所以作为参数的宏先展开,相当于
puts(s(ab));—–>puts(d(ab));—->puts(#ab);—->puts(“ab”);
define f(a,b) a##b
define d(a) #a --》 以”#”开头的,直接替换,不展开:immediately replaced by the unexpanded actual argument
define s(a) d(a) --》 非以”#”开头的,先展开,再替换,也就是一般的情况
所以就两种情况:
1,不以”#”开头的,先展开参数a,然后是替换代码:puts(s(f(a,b)));–>puts(s(ab))–>puts(d(ab))–>puts(“ab”)
2,以”#”开头的,直接替换,不展开:puts(d(f(a,b)))–>puts(“f(a,b)”)
include
define DIRECT_LITERAL(a) #a
define INDIRECT_LITERAL(a) DIRECT_LITERAL(a)
int main(void)
{
puts(DIRECT_LITERAL(INDIRECT_LITERAL(a + b)));
puts(INDIRECT_LITERAL(DIRECT_LITERAL(a + b)));
return 0;
}
这其实从编译角度的展开归约也可以理解啊。
以上代码第一种情况,当预编译器看到DIRECT_LITERAL后查到它是宏定义,定义为#a,此时后面的参数部分就会以#a的形式生成到源文件中。也就是说,预编译后的源文件中,替代第一条语句的就是:
puts(“INDIRECT_LITERAL(a + b)”);输出则是INDIRECT_LITERAL(a + b)
而对于第二条语句,当预编译器看到INDIRECT_LITERAL后查到它是宏定义,定义为DIRECT_LITERAL(a),这时先把它作为DIRECT_LITERAL(DIRECT_LITERAL(a + b))的形式暂存起来,你也可以理解为这个状态是语法树的当中一个叶结点。然后再分析后面的DIRECT_LITERAL后面的参数部分,即:DIRECT_LITERAL(a + b),同样,预编译器会将它归约为”a + b”的形式。这样对于里面的DIRECT_LITERAL(a + b)的形式就完全确定下来了,那么这个值就可以充当叶子结点,即它底下不会再有结点。然后再回到刚才那个状态,DIRECT_LITERAL(“a + b”)最后就是”\”a + b\”“。所以这里输出是”a + b”。
值得注意的是#a是将参数a转为字符串形式。所以像DIRECT_LITERAL(a)的展开形式是字符串常量”a”
那么DIRECT_LITERAL(“a”)展开就是”\”a\”“。
include
define DIRECT_LITERAL(a) #a
define INDIRECT_LITERAL(a) DIRECT_LITERAL(a)
define DIRECT_CAT(a, b) a##b
define INDIRECT_CAT(a, b) DIRECT_CAT(a, b)
int main(void)
{
puts(DIRECT_LITERAL(INDIRECT_LITERAL(a + b)));
puts(INDIRECT_LITERAL(DIRECT_LITERAL(a + b)));
puts(INDIRECT_LITERAL(DIRECT_CAT(INDIRECT_CAT(a, b), INDIRECT_CAT(c, d))));
puts(INDIRECT_LITERAL(INDIRECT_CAT(DIRECT_CAT(a, b), DIRECT_CAT(c, d))));
return 0;
}
- define 中的#,##和#@
- #define中的rettype和##
- define 中的#,##和#@
- #define 中的“#”和“##”
- #define宏中的“#”和“##”
- define 中的 ## 和 #
- #define中的#和##作用
- define标准中的 # 和 ## 操作
- PHP 中的 global 和 define
- #define 中的“ # 运算符”和“ ## 运算符”
- #define 中的“ # 运算符”和“ ## 运算符”
- c/c++中的#ifndef和#define
- 浅谈C/C++中的typedef和#define
- C/C++中的typedef、#define和const
- 浅谈C/C++中的typedef和#define
- 浅淡C/C++中的typedef和#define
- Racket中的define、let和let*
- 浅淡C/C++中的typedef和#define
- 关于字体大小设置用dp还是sp
- 假期第一周周报
- 为什么不能用memcached存储Session?
- 导出表空间名称为V3SNS的数据后,导入数据库步骤
- ubuntu下apt-get 命令参数
- #define 中的“#”和“##”
- 在linux中使用vi 打开文件时,能显示行号吗?http://zhidao.baidu.com/link?url=km4N-VLhK1DtSUOexgWMiZ73tp7R91g2UhZ15eTZv4
- C 基础知识点讲解1
- android 开发画虚线、实线,画圆角矩形,一半圆角
- iOS学习之动画效果的实现
- [Microsoft][SQLServer 2000 Driver for JDBC]Error establishing socket错误解决方法总结
- 简单并查集之按秩合并——The Suspects
- 如何评价电影《西游记之大圣归来》?
- HDU5312string类的字符串赋值函数和查找函数