C++乱码从入门到放弃
前几天在一篇文章中看见一段用大括号包裹的C++代码(大概长下面这样)
{ //一些必要的预处理代码...吧啦吧啦吧啦... int main() { //代码主体...吧啦吧啦吧啦... } }
当时我一脸懵逼,这是神马语法,能通过编译?于是乎我把这段代码COPY进了我的Dev编译器,Amazing!居然 编译顺利过,运行也没出错!我突发奇想,如果能在代码中放一段乱码 还不出错 岂不是一件很装逼的事,于是便有了下面这段代码
#include<iostream> using namespace std; int main() { //我是一段用脸滚的乱码 '*';{1=='\\'+'`'?('$'):1;/***/~~~~!!!((+-+-0001/'\''|1/0x9));};;;qdsojntbz:///0]=d\f@w|e%sv)vs%$^&d*(# //我是一段用手敲的代码 cout << "新年快乐呀!" << endl; return 0; }
把上面的代码COPY进你的编译器里运行,你会发现它不仅顺利通过了编译,还成功输出了”新年快乐呀!”,这说明上面那段乱码符合C++语法的,那到底怎样的无意义代码符合语法呢,经过我十多分钟的测试,这里来做一个总结(如果发现错误或有补充请通过下方评论区或通过公告栏中的邮箱告诉我,阿里嘎多!)
首先是最简单的注释(没学过注释的读者也不要急,后面我会专门写一篇文章讲解注释的),/***/和///都是常见的注释美化小技巧,其中/***/中的第二个*和///中的最后一个/都是注释内容,被编译器自动省略,所以不会引起任何错误,我可以像下面这样写注释
/////////////////////////////// /// /* /// /// *编辑 at 2020年1月14日 /// /// *编辑 by Space Time /// /// /* /// ///////////////////////////////
接下来便是块和语句的开始和结束符了,开篇那段故事讲得便是它,{是块的开始符,}是块的结束符,块中可以写入代码,也可以不写任何东西(空块),例如main(){return 0;}中的{}就是一个写入了return 0;的块,而main(){}中的{}就是一个空块,块也可以在代码中单独出现,所以下面这段代码是符合语法的
{ int main() {{{{}}}} }
语句的结束符;也可以单独出现(空语句),所以下面这段代码也是符合语法的
int main() { ; ;;;; ;;;;;;; ;;;;;;;;;; }
再接下来是字面量,字面量可以作为一个语句单独出现,另外用于提高优先级的()是可以套无数层的,所以下面这段代码还是符合语法的
int main() { "C++是世界上最好的语言!"; 3.14159;
(((3.14159)));
1 + 1;
true + false;
"你大爷" == "你大爷";
}
切记不要出现++1这种错误(因为1是右值),看懂了上面这段代码,我们再看看下面这段奇葩的代码
int main() { +-1; }
这既不+又不-的玩意到底是个什么鬼啊,but actually,它还是符合语法的,这里的+和-可以理解为正和负,所以+-1其实就是-1,但是由于两个+连在一起就变成了++1(会报错),两个-连在一起就变成了–1(也会报错),所以在写这种字面量时必须一+一-地交替写,还弄不清楚可以参考下面这段代码
int main() { +1; //通过 -1; //通过 +-1; //通过 ++1; //报错 --1; //报错 --+1 //报错 +-+-1; //通过 -+-+-+1; //通过 }
最后一个也是最难想到的,先来看下面这段代码
int main() { CppNB: }
注意CppNB后面的结束符是:而不是;,没想到吧,这段代码又双叒叕是符合语法的(不用怀疑,我瞎敲得代码永远是符合语法的),这是因为goto语句的标记是以:结尾的,所以只要你在:前敲的乱码符合goto标记的命名规范,它就不会报错(其实goto标记的命名规范和变量的命名规范是一样的)
看到这里你大概已经能够看懂开头那段我用脸滚的代码了,如果你还是看不懂,那可能是因为你不知道下面这些:
1.C++中以0开头的字面量是八进制数
2.C++中以0x开头的字面量是十六进制数
2./是÷的意思
4.|是逻辑运算符 或
5.!是逻辑运算符 非
6.~是位运算符 按位取反
-6.\\是转义字符 \
7.\’是转义字符 ‘
8.’可以隐式转换为它对应的ASCLL码(我记得好像是39)
9.三目运算符语法是 判断我是true还是false?是ture取我:是false取我; (具体请自行谷歌)
0.我不太会数数
9.点完赞你就看得懂了 •ᴗ•