免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3205 | 回复: 13
打印 上一主题 下一主题

## 用法 [复制链接]

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:49:03
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-04-30 06:16 |只看该作者 |倒序浏览
本帖最后由 shihyu 于 2010-04-30 06:18 编辑

The C Programming Language

A.12.3 Macro Definition and Expansion

  1. #define cat(x, y) x ## y
  2. #define xcat(x, y) cat(x,y)
  3. xcat(xcat(1, 2), 3)
复制代码
可以得到 123

  1. #define xcat(x, y) cat(x,y)
  2. xcat(xcat(1, 2), 3)
复制代码
得到 cat(cat(1,2),3)
  1. #define cat(x, y) x ## y
  2. cat(cat(1,2),3)
复制代码
那为什么直接用#define cat(x, y) x ## y无法变成123?


谢谢

论坛徽章:
0
2 [报告]
发表于 2010-04-30 07:52 |只看该作者
本帖最后由 numdisp 于 2010-04-30 07:54 编辑

这个以前还真没注意过,不过根据gcc的出错信息,推测第3个例子失败的原因是:

预处理是“从外到内的”,或者说,是根据出现的先后次序来进行处理的,它只是简单地逐个扫描并替换而已,并不想编译器那么“聪明”,知道递归的概念。

第3个例子中,"cat(cat(1,2),3)" 首先被展开成 "cat(1,2)3",结果遇到了 cat(1,2)3 这样一个“无效”的表达式,就停止了。

gcc -E 的错误如下:
error: pasting ")" and "3" does not give a valid preprocessing token
cat(1,2)3

仅推测而已,未在理论上证实,请真正研究过预处理器的人确认一下。

论坛徽章:
0
3 [报告]
发表于 2010-04-30 08:05 |只看该作者
问题在于,这是宏,不是函数。先碰到的可能会先展开。
#define cat(x, y) x ## y
cat(cat(1,2),3)
会变成
cat(1,2)3
这样就有语法错误了。

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:49:03
4 [报告]
发表于 2010-04-30 13:36 |只看该作者
  1. #define cat(x, y) x ## y
  2. #define xcat(x, y) cat(x,y)
  3. xcat(xcat(1, 2), 3)
复制代码
不过改成这样就可以变成 123 , 这又是什么原因?

谢谢

论坛徽章:
0
5 [报告]
发表于 2010-04-30 14:18 |只看该作者
本帖最后由 numdisp 于 2010-04-30 14:22 编辑

感情楼主是专门来考大家认真看过书没有的啊(还专门把章节号都列出来了)。
K&R的书上说的很清楚了:
However, the call cat(cat(1,2),3) is undefined: the presence of ## prevents the arguments of the outer call from being expanded. Thus it produces the token string
cat ( 1 , 2 )3
and )3 (the catenation of the last token of the first argument with the first token of the second)
is not a legal token. If a second level of macro definition is introduced,
#define xcat(x, y) cat(x,y)
things work more smoothly; xcat(xcat(1, 2), 3) does produce 123, because the expansion
of xcat itself does not involve the ## operator.

K&R, The C Programming Language, Second Edition. P190, Appendex A.12.3

关键是 ## 导致了预处理停止了最终解析。

论坛徽章:
0
6 [报告]
发表于 2010-04-30 18:50 |只看该作者
学习了

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:49:03
7 [报告]
发表于 2010-04-30 19:50 |只看该作者
If a second level of macro definition is introduced<--- 这句话是在先用 #define xcat(x, y) cat(x,y) 展开吗?

用下面三段宏可以正常得到 123
#define cat(x, y) x ## y
#define xcat(x, y) cat(x,y)
xcat(xcat(1, 2), 3)


上面三段宏可以展开可以得到123 , 但我不懂的是下面两段宏展开之后
#define xcat(x, y) cat(x,y)
xcat(xcat(1, 2), 3)
会得到
cat(cat(1,2),3)
之后再用 #define cat(x, y) x ## y 宏把   cat(cat(1,2),3) 展开得到 123?


如果我这样跟直接用下面两段宏展开为什么就不行?  
#define cat(x, y) x ## y
cat(cat(1,2),3)



下面处理展开步骤是怎样的可以说一下过程吗?
#define cat(x, y) x ## y
#define xcat(x, y) cat(x,y)
xcat(xcat(1, 2), 3)



谢谢

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
8 [报告]
发表于 2010-04-30 22:57 |只看该作者
C标准说的很明白。在读到宏的时候,读入宏所有的参数,如果参数没有跟在#和##的后面或者##的前面,那么先展开所有的参数,最后用展开的参数进行替换。所以

#define cat(x,y) x ## y
#define xcat(x,y) cat(x,y)
xcat(xcat(1,2),3)
的过程是这样的:
xcat(xcat(1,2),3) -> xcat(cat(1,2), 3) -> xcat(12, 3) -> cat(12,3) -> 123

而cat(cat(1,2),3)
的过程是这样的:
cat(cat(1,2),3) -> cat(1,2)3
而)3并不是一个正确的token,于是产生未定义行为。

作为练习,
xcat(cat(1,2),3) -> xcat(12,3) -> 123
而:
cat(xcat(1,2),3) -> xcat(1,2)3 -> undefined behavior

论坛徽章:
0
9 [报告]
发表于 2010-04-30 23:37 |只看该作者
小翼同志讲的好!

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:49:03
10 [报告]
发表于 2010-05-01 02:20 |只看该作者
C标准说的很明白。在读到宏的时候,读入宏所有的参数,如果参数没有跟在#和##的后面或者##的前面,那么先展 ...
starwing83 发表于 2010-04-30 22:57



xcat(xcat(1,2),3) -> xcat(cat(1,2), 3) -> xcat(12, 3) -> cat(12,3) -> 123
cat(cat(1,2),3) -> cat(1,2)3

如果参数没有跟在#和##的后面或者##的前面,那么先展开所有的参数,最后用展开的参数进行替换。
上面这句话意思有意思说明展开顺序吗?


xcat(xcat(1,2),3) -> xcat(cat(1,2), 3) -> xcat(12, 3) -> cat(12,3) -> 123    <--- 为什么从里面开始展开?

cat(cat(1,2),3) -> cat(1,2)3  <--- 为什么从外面开始展开?


谢谢
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP