Chinaunix首页 | 论坛 | 博客
  • 博客访问: 207088
  • 博文数量: 32
  • 博客积分: 1025
  • 博客等级: 少尉
  • 技术积分: 315
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-13 15:54
文章分类

全部博文(32)

文章存档

2011年(30)

2010年(2)

我的朋友

分类: C/C++

2011-03-26 16:33:21


嵌套注释

C90只有一种注释风格,就是使用“/*”和“*/”。早在预处理阶段,C预处理器就会剔除所有出现在“/*”和“*/”之间的内容(包括这对记号本身),所以在接下来传送到C编译器的代码文件里是不会出现任何注释内容的。


但这么简单的注释风格有时也会令人头疼。例如,你可能想,什么是注释呢?注释就是写什么东西都无所谓,反正编译器不会看到这些东西。很不幸,C预处理器一般都不支持嵌套注释,如果你这样写:

       /*something /* something else */*/

       是行不通的。因为预处理器在碰到第一个“*/”时就认为注释已经结束!于是它把到这里为止的注释移除,可想而知,结果留下孤零零一个“*/”—编译程序又报错了。

       这样的处理常常令我们很不舒服,例如有时我们调试代码,需要把连续几行代码注释掉观察结果,做法自然是这样写:

       语句1;

              语句2;

              /*

                     语句3;

              */

              语句4;

       语句5;

       但随着调试的深入,可能我们想连语句2、语句4都注释掉:

       语句1;

       /*

              语句2;

              /*

                     语句3;

              */

              语句4;

       */

       语句5;

       多加一对注释不就解决了?

       --中招了。看,你用了嵌套注释。

       为了解决这个问题,C++引入另一种风格的注释:使用“//”。预处理器会删除从“//”开始到后面碰到的第一个换行符之间的所有内容。这样就没有嵌套注释的问题了,只不过书写有点繁琐,例如:

       语句1;

       //语句2;

       //语句3;

       //语句4;

       语句5;

       你喜欢注释哪一行都可以,随时可以撤消注释,干脆利落,绝对没有副作用,当然,前提是你一行只写一个语句。

       资深程序员一般都更乐意使用C++风格的注释,我也如此建议。不过,你会问,C预处理器可不认识“//”啊?

       其实多数C预处理器都“暗中”支持“//”,除非你使用“严格符合C90”之类的编译选项,否则C预处理器是不会阻挠你的。

       而且,有个好消息:

       C99已经正式采纳C++的注释风格,在今后,你可以光明正大的使用“//”。当然,原来的老风格仍然可以继续使用。

       不过,大家最好不要“一只脚踏两只船”,像这样就不好:

       // /* 语句1;

       语句2;

       */

       语句3;

       原先用“/*”和“*/”注释掉语句1和语句2,现在不小心又加上“//”,出错了。因为预处理器一看见“//”就不管三七二十一把“///* 语句1;”全部删除掉,结果又留下一个“*/”没有处理。

       结束本节之前,再讨论一个有趣的问题。

       有些敏感的读者已经坐不住了:那万一我想在字符串里包含“//”之类的注释符怎么办?譬如我要在屏幕上显示这么一行:

       we have a // in this line.

 能够这样写吗:

       printf(“we have a // in this line.\n”);

       答案是可以的,只要记住三条原则:

       #1 字符串里面的注释符不起注释作用;

       #2 注释符里的双引号不起标识字符串的作用;

       #3 如果情况混乱则从头找起。

       例如:

       printf(“we have /* and */ here.”);

       则根据原则#1,最后打印出来的字符串不会缺少“/* and */”这部分。

       // “This line is a comment.”

       由原则#2,可以肯定这一行会被注释掉。

       /* “ */ “ */

       你可能这样想,第一个“*/”在双引号里面,噢,它不起注释作用,所以这一行被完全注释掉。

       不是的。在这么“恶劣”的环境下,我们要找出最先出现的符号是注释符还是双引号,在这个例子里,注释符最先带头,所以根据原则#2,双引号不起任何作用,当预处理器碰到第一个“*/”时就认为注释结束,预处理的结果是上面这一行语句最后剩下:

       “ */

       另:

       其实C/C++程序员可以使用预处理指令实现嵌套注释:

       语句1;

              #if 0

                     语句2;

                            #if 0

                                   语句3;

                            #endif

                     语句4;

              #endif

       语句5;

       因为预处理器在分析预处理指令时不仅进行词法分析,还进行语法分析,这就比使用“/*”和“*/”高级,后者仅仅涉及词法分析。

两个小例子:

例一:

/*/**/"*/"/*"/**/ 
在不允许嵌套注释的编译器中相当于 "*/" 
不允许嵌套的从前往后寻找配对 找到即开始注释 
故/*/**/"*/"/*"/**/    ->    "*/"/*"/**/   ->   "*/" 


在允许嵌套注释的编译器中相当于 "/*" 
允许嵌套的找到最后一个左边符号 然后开始寻找配对 找到即开始注释 
故/*/**/"*/"/*"/**/   ->    /*"*/"/*"/**/ ->   "/*"/**/   ->    "/*" 


例二: 
/*/*/0*/**/1 
在不允许嵌套注释的编译器中相当于 0*1 
在允许嵌套注释的编译器中相当于 1 

来源:《C 陷阱与缺陷》 
阅读(4696) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~