嵌套注释
这个问题来自《C Traps and Pitfalls》
请编写一个测试程序,要求无论是对允许嵌套注释的编译器,还是对不允许嵌套注释的编译器,该程序都能正常编译(无错误消息出现),但是这两种情况下程序执行的结果却不相同。
提示:在用双引号括起的字符串中,注释符 /*
属于字符的一部分,而在注释中出现的双引号 ""
又属于注释的一部分
首先你可能会想,什么是嵌套注释
从编译器的角度来说,就是当处理注释的过程中,是允许继续读入 /* */
这样的符号的
比如一个字符串 /*/**/
, 对于可以嵌套注释的编译器来说, 这是一个未完成的注释,也就是说,后面的任何内容都将被解析为注释,因为第一个 /*
没有找到他对应的 */
那么对于不可以嵌套注释的来说,这就是一段完整的注释,其中注释的内容为 /*
,因为解析规则是这样的,编译器看到了一个注释开始符号,然后将后面的所有字符都解析为注释,直到遇到 */
才结束
更形象点来说,嵌套注释就像是括号匹配,我们有一个计数器 cnt
,遇到 /*
我们就 cnt++
, 遇到 */
我们就 cnt--
,那么对于任何时刻的字符来说,当且仅当 cnt != 0
时,我们将其看做注释
而不允许嵌套注释的情况下,我们有一个 flag
, 最开始是假,当我们遇到 /*
的时候我们将 flag
设为真, 遇到 */
时我们将 flag
设为假, 那么对于任何时刻的字符来说,当且仅当 flag == true
时,我们将其看做是注释
当理解清楚嵌套注释和非嵌套注释的区别了以后,我们就可以根据他们的性质来针对性的进行构造
考虑这样一个字符串 /*/**/*/
对于允许嵌套的编译器来说,这就是一段注释,而对于不允许嵌套的编译器来说,这一段代表了 */
(虽然看上去每一段注释都闭合了,但是从左向右模拟一遍就可以发现问题)
这时候就需要题中提示的来帮助我们解决问题了,我们需要用注释符和双引号来配合
关键在于我们解析注释的方法变了的同时,注释的区域也发生了改变
我们用双引号包围最后的注释结束符,/*/**/"*/"
,那么对应的非嵌套版本就是 "*/"
,而嵌套版本就是 "
现在我们希望闭合这个双引号,如果我们在字符串后面加上 /*"*/
,将不会对非嵌套版本造成影响,但是在闭合引号的同时,我们也在后面加上了 */
,那么我们考虑加上 /*"/**/
即可
最终结果就是 /*/**/"*/"/*"/**/
原书中有这道题的答案,写的也很棒,十分推荐看一下。
文章评论