Jam*_*lis 12 c++ c-preprocessor
请考虑以下宏定义和调用:
#define x x[0]
#define y(arg) arg
y(x)
Run Code Online (Sandbox Code Playgroud)
此调用扩展为x[0](在Visual C++ 2010,g ++ 4.1,mcpp 2.7.2和Wave上测试).
为什么? 具体来说,为什么不扩展到x[0][0]?
在宏替换期间,
在扩展了包含在其中的所有宏之后,替换列表中的参数...被相应的参数替换.在被替换之前,每个参数的预处理标记都被完全宏替换(C++03§16.3.1/ 1).
评估宏调用,我们采取以下步骤:
y调用类函数宏x作为其arg参数的参数x在参数是宏观替换成为x[0]arg在替换列表由参数的宏代替值代替,x[0]替换所有参数后的替换列表是x[0].
替换替换列表中的所有参数后,重新扫描生成的预处理标记序列...以替换更多的宏名称(C++03§16.3.4/ 1).
如果在替换列表的扫描期间找到要替换的宏的名称...则不会替换它.此外,如果任何嵌套替换遇到要替换的宏的名称,则不替换它(C++03§16.3.4/ 2).
x[0]重新扫描替换列表(请注意,要替换的宏的名称是y):
x 被标识为类似对象的宏调用x 被替换为 x[0]由于§16.3.4/ 2中的规则阻止了递归,因此此时替换停止.重新扫描后的替换列表是x[0][0].
我清楚地误解了一些东西,因为我测试的所有预处理器都说我错了.此外,这个例子是C++ 0x FCD(§16.3.5/ 5)中的一个更大的例子,它也表示预期的替换是x[0].
x在重新扫描期间为什么不更换?
C99和C++ 0x实际上与引用部分中的C++ 03具有相同的措辞.
Ste*_*sop 17
我相信你已经引用了关键段落,你刚刚停止了.16.3.4/2(强调我的):
如果在替换列表的扫描期间找到要替换的宏的名称(不包括源文件的其余预处理标记),则不会替换它.此外,如果任何嵌套替换遇到要替换的宏的名称,则不会替换它.这些未替换的宏名称预处理令牌不再可用于进一步替换,即使它们稍后(重新)检查在其中否则将替换该宏名称预处理令牌的上下文中.
所以,当x被替换x[0]的参数替换时y,它完全取代宏,这意味着它是在这一点上重新扫描,并x通过递归规则抓获.这意味着xin x[0]不再有资格进行进一步替换,包括在重新扫描部分扩展结果期间y(x).
| 归档时间: |
|
| 查看次数: |
823 次 |
| 最近记录: |