环球简讯:这c代码,会让你发疯
之前我写过一段代码,文章如下
c语言从1打印到100再打印到1该如何编写?
这是一个很简单的代码,可能刚学c语言没几天的人都知道用一个for循环就可以搞定。
(资料图)
#include"stdio.h"voidfun(intn){if(n<100){printf("%d",n);fun(n+1);}printf("%d",n);}intmain(void){fun(1);return0;}
但是有一个读者朋友看了我的文章,发了这样一段代码过来
__[]={1,10,100,1000};main(_){_^400&&(_<4?1:putchar(((!((_/4)/((_%4)["3210"][__-48])%10)&&(_%4)^3)?32:((_/4)/((_%4)["3210"][__-48])%10+48))))&&main(-~_);putchar(((!(((_+3)/4)/(((3+_)%4)["0123"][__-48])%10)&&((3+_)%4)^0)?_^398?32:48:(((3+_)/4)/(((3+_)%4)["0123"][__-48])%10+48)))&&_^1?1:putchar(10);}
这位读者朋友的叫做,「我们国庆的时候,还针对这几个题目聊了两天,技术原来真的可以拉近大家的距离。」
如果没解析,是很难理解这样非人类的代码的,里面运用到的几个技巧如下
main 函数是可以递归的,这也是很多大神写代码用到的一个技巧。
main 函数是可以没有返回值的,当然,编译的时候会出现警告,但是这并不影响运行结果。
argc != 8 等价于 argc^8
argc +1 等价于 -~argc
&& 和 || 等存在短路操作
数组 a[i] 等价于i[a]
56,可以通过取整取余通过putchar把他们打印出来
所以上面的代码就可以拆解成
__[]={1,10,100,1000};main(_){if(_!=20){if(_>=4){putchar(((!((_/4)/((_%4)["3210"][__-48])%10)&&(_%4)^3)?32:((_/4)/((_%4)["3210"][__-48])%10+48)));}main(-~_);}putchar(((!(((_+3)/4)/(((3+_)%4)["0123"][__-48])%10)&&((3+_)%4)^0)?_^398?32:48:(((3+_)/4)/(((3+_)%4)["0123"][__-48])%10+48)))&&_^1?1:putchar(10);}
400 是用来控制输出的数量的,我们现在是输出 1~100~1
看下ascii码表,32对应的是空格,48 对应的是字符 ’0‘
然后,我们可以得出这样的解释代码
重要的部分都写在注释里面了,大家可以认真看看。
__[]={1,10,100,1000};main(_){if(_!=100){if(_>=4){charc=32;//默认打印输出一个空格‘’intnumber=_/4;//这个是实际输出的数字,如果_等于[1,2,3,4],不会进入这个循环,如果_等于[4,5,6,7],number就等于1,取整数部分。intbit=(_%4)["3210"][__-48];//这个就是数组取巧的地方,bit等于1,10,100,1000,其中的一个数字,记住48对应的ascii是字符‘0’//先推导(_%4)["3210"]这部分得出结果,之后再推导(_%4)["3210"][__-48]//(x)[y]等价于*(y+x)intbitnumber=number/bit%10;//bitnumber可以认为是有效数字的推导,如果是[4,5,6,7],打印出来对应的应该是[‘空格’,‘空格’,‘空格’,‘1’]//所以这里的判断主要是为了让下面的if不要成立就可以了。//sampleinput:4567//number:1111//bit:1000100101//bitnumber:0001//当然,如果输入的数字很大呢?//sampleinput:44454647//number:11111111//bit:1000100101//bitnumber:0011//sampleinput:40414243//number:10101010//bit:1000100101//bitnumber:0010//上面的推导就是完成了下面的if语句,bitnumber !=0是为了输出超过10位数的数。//_%4 == 3, 是为了输出整除4个数字的最后一位。if((_%4==3)||bitnumber!=0)c=bitnumber+48;putchar(c);}main(-~_);}putchar(((!(((_+3)/4)/(((3+_)%4)["0123"][__-48])%10)&&((3+_)%4)^0)?_^398?32:48:(((3+_)/4)/(((3+_)%4)["0123"][__-48])%10+48)))&&_^1?1:putchar(10);}
至于下面的一行解释和上面的如出一撤,比较关键的地方是,这里用到了递归
调用,所以对栈的大小是有要求的。
可以试试
作者给出的详细解释如下
两份解析一起来看的话,希望大家对代码的理解有所帮助,当然了,写这样的
代码出来也是非常有意思。
相关阅读
-
世界热推荐:今晚7:00直播丨下一个突破...
今晚19:00,Cocos视频号直播马上点击【预约】啦↓↓↓在运营了三年... -
NFT周刊|Magic Eden宣布支持Polygon网...
Block-986在NFT这样的市场,每周都会有相当多项目起起伏伏。在过去... -
环球今亮点!头条观察 | DeFi的兴衰与...
在比特币得到机构关注之后,许多财务专家预测世界将因为加密货币的... -
重新审视合作,体育Crypto的可靠关系才能双赢
Block-987即使在体育Crypto领域,人们的目光仍然集中在FTX上。随着... -
简讯:前端单元测试,更进一步
前端测试@2022如果从2014年Jest的第一个版本发布开始计算,前端开发... -
焦点热讯:刘强东这波操作秀
近日,刘强东发布京东全员信,信中提到:自2023年1月1日起,逐步为...