IOCCC大赛代码分析笔记
源代码如下:
main(_){_^448&&main(-~_);putchar(--_%64?32|-~7[__TIME__-_/8%8][">'txiZ^(~z?"-48]>>";;;====~$::199"[_*2&8|_/64]/(_&2?1:8)%8&1:10);}
结果是用!号显示当前的时间。
为了理解代码,首先整理下:
- 规范主函数,加入头文件,并用i代替参数_
#include <stdio.h>
int main(int i)
{
i^448&&main(-~i);
putchar(--i%64?32|-~7[__TIME__-i/8%8][">'txiZ^(~z?"-48]>>";;;====~$::199"[i*2&8|i/64]/(i&2?1:8)%8&1:10);
return 0;
}
- 其中~ 按位取反,对于有符号int,
~i+1+i=0
,因此-~i=i+1
。并且&&
运算符是短路求值,当左值为真的时候,才会对右值求值,进入递归。改写之后,写成
#include <stdio.h>
int main(int i)
{
if(i^448)
main(i+1);
putchar(--i%64?32|-~7[__TIME__-i/8%8][">'txiZ^(~z?"-48]>>";;;====~$::199"[i*2&8|i/64]/(i&2?1:8)%8&1:10);
return 0;
}
i^448
等价于i!=448
中间是一个一个? :
运算符,展开之后得到
#include <stdio.h>
int main(int i)
{
if(i!=448)
main(i+1);
i=i-1;
if(i%64)
putchar(32|-~7[__TIME__-i/8%8][">'txiZ^(~z?"-48]>>";;;====~$::199"[i*2&8|i/64]/(i&2?1:8)%8&1);
else
putchar(10);
return 0;
}
- main的默认命令行输入参数是0个,将递归改写成循环,因为从0开始进入递归,当448的时候才putchar后return,所以循环从448开始,又由于有
--i
,所以,从447开始递减到0。
#include <stdio.h>
int main(int i)
{
for(i=447;i>=0;--i)
{
if(i%64)
putchar(32|-~7[__TIME__-i/8%8][">'txiZ^(~z?"-48]>>";;;====~$::199"[i*2&8|i/64]/(i&2?1:8)%8&1);
else
putchar(10);
}
return 0;
}
- 10的ascii码是\n换行。
__TIME__
是一个8位的字符数组,">'txiZ^(~z?"
是一个11位的字符数组,";;;====~$::199"
是一个14位的字符数组,将三个变量拎出来得到
#include <stdio.h>
int main(int i)
{
char a[9]=__TIME__;
char b[12]=">'txiZ^(~z?";
char c[15]=";;;====~$::199";
int temp;
for(i=447;i>=0;--i)
{
temp=-~7[a-i/8%8][b-48]>>c[i*2&8|i/64]/(i&2?1:8)%8;
if(i%64)
putchar(32|temp&1);
else
putchar('\n');
}
return 0;
}
- []的优先级最高,同时注意到
7[a]=a[7]
,右移运算符>>优先级在-~之下,但是在位与&和位或|之前。temp对8取余,因此temp在0到7之间。位与&在位或|之前。32|temp&1的结果如下表所示
temp | ASCII |
---|---|
0 | 33 ! |
1 | 33 ! |
2 | 35 # |
3 | 35 # |
4 | 37 % |
5 | 37 % |
6 | 39 ’ |
7 | 39 ’ |
2019年7月16日17:15:01未完待续
2019年7月16日18:33:23更新
其中7[a-i/8%8][b-48]=b[ a[7-i/8%8]-48 ]
,a[7-i/8%8]
取的是char型,48的ascii码是0,一个char型-48等于转换为int型。其中i/8%8
每64个数一次轮回,打印一个\n,显示时间结果也是7*64的矩阵。__TIME__时间显示格式表示为H1H2:M1M2:S1S2。因此
i | i/8%8 | a[7-i/8%8] |
---|---|---|
0~7 | 0 | S2 |
8~15 | 1 | S1 |
16~23 | 2 | : |
24~31 | 3 | M2 |
32~39 | 4 | M1 |
40~47 | 5 | : |
48~55 | 6 | H2 |
56~63 | 7 | H1 |
:的ASCII码是58,所以对应的b表如下
a[7-i/8%8]-48 | b[ a[7-i/8%8]-48 ] | ASCII | -~7[a-i/8%8][b-48] |
---|---|---|---|
0 | > | 62 | 63 |
1 | ’ | 96 | 97 |
2 | t | 116 | 117 |
3 | x | 120 | 120 |
4 | i | 105 | 106 |
5 | Z | 90 | 91 |
6 | ^ | 94 | 95 |
7 | ( | 40 | 41 |
8 | ~ | 126 | 127 |
9 | z | 122 | 123 |
: | ? | 63 | 64 |
看看右移后面的项c[i*2&8|i/64]/(i&2?1:8)%8
:
i | i&2 | (i&2?1:8) | i*2&8 | i*2&8|i/64 | c[i*2&8|i/64] | c[i*2&8|i/64]/(i&2?1:8)%8 |
---|---|---|---|---|---|---|
0 | false | 8 | 0 | 0 | ; 59 | 7 |
1 | fasle | 8 | 0 | 0 | ; 59 | 7 |
2 | true | 1 | 0 | 0 | ; 59 | 7 |
3 | true | 1 | 0 | 0 | ; 59 | 7 |
4 | false | 8 | 8 | 8 | $ 36 | 4 |
5 | fasle | 8 | 8 | 8 | $ 36 | 4 |
6 | true | 1 | 8 | 8 | $ 36 | 4 |
7 | true | 1 | 8 | 8 | $ 36 | 4 |
i从0~447分为7层,每层都会有变化
i 的层数 | c[i*2&8|i/64] | c[i*2&8|i/64]/(i&2?1:8)%8 |
---|---|---|
0 | ; 59 和 $ 36 | 77334444 |
1 | ; 59 和 : 58 | 77337722 |
2 | ; 59 和 : 58 | 77337722 |
3 | =61和 ‘1’ 49 | 77556611 |
4 | =61和 ‘9’ 57 | 77557711 |
5 | =61和 ‘9’ 57 | 77557711 |
6 | =61和 ‘\0’ 0 | 77550000 |
2019年7月16日20:22:34 未完待续