当前位置: 首页 > 科技观察

一行注释也能影响运行结果吗?

时间:2023-03-11 22:22:34 科技观察

没想到一行注释也能影响运行结果!或许你在某段听说过,删除某行注释后,程序无法正常执行?真的是这样吗?别相信。见证“奇迹”#include#includeintmain(void){inta=(int)sqrt(30);//issqrt(30)+1>5??///故意让a++,不用担心为什么a++;if(a>5)printf("sqrt(30)+1>5\n");else{printf("sqrt(30)+1<=5\n");}return0;编译运行:$gcc-omainmain.c-trigraphs$./mainsqrt(30)+1>5作为受过九年义务教育的我们,可以看出结果是正确的。毕竟5*5<30<6*6。但是删除第九行,然后运行:$./mainsqrt(30)+1<=5结果变了!!看到这里,细心的读者可能已经发现了端倪,我就不赘述了。接下来说说我们这次要说的主角——三字母序列。三字符组我们都知道C语言中有很多转义符号,例如:\n换行符(LF)\r回车符(CR)\thorizo??ntaltab(HT)\bbackspace(BS)\'单引号\"double引号\\反斜杠...当然还有很多,我就不一一列举了。这些符号在代码中有特殊的作用,或者不能直接输入,所以用转接符号+其他字符组合代替。同理,有些早期的键盘可能无法输入一些特殊符号,比如:#$@[\]^`{|}~所以,为了解决这个问题,C语言标准规定了预处理,当C预处理器(Cpreprocessor)扫描并处理C语言源文件,将后面的3个字符替换为1个字符:即??/将替换为\,如果删除原来的第9行,则变为://issqrt(30)+1>5\a++;我们都知道\的存在(通常一行代码太长,可以用这个符号来换行),m使上面看起来像两行,但实际上是一行。也就是说变成://issqrt(30)+1>5a++;也就是说a++根本不会执行,当然最后的结果也不符合预期。当然,很多现代的编译器可能不会做这样的替换,所以基本上不用担心这样的问题,直接使用原来的符号即可。其实细心的读者可能已经注意到,我在前面的示例代码中加入了编译选项-trigraphs,否则编译时会出现警告:$gcc-omainmain.cmain.c:Infunction'main':main.c:6:27:warning:trigraph??/ignored,use-trigraphstoenable[-Wtrigraphs]//issqrt(30)+1>5??/双字符组除了三字符,还有双字符组。总结一下,今天你不知道踩坑难,知道了也没用的内容就介绍到这里了。