c语言获奖程序,1987年国际C语言混乱代码大赛获奖的一行代码

最近CoolShell博主做了一个很有意思的在线puzzle,这些谜题很有趣同时也有一定的难度。由于水平有限,我并没有通关,我觉得这些题还是很值得一做的,从中可以学到很多东西。

例如其中的第二题:

0818b9ca8b590ca3270a3433284dd417.png

题目中给出了一个键盘和一行看不懂的字符串。我们发现这个键盘的键盘布局和现在通用的键盘(QWERTY键盘)不一样,它叫做要通过两种键盘的布局映射,将给出的字符串转换成QWERTY键盘下的输出。当然,你可以自己一对一写出来,不过在线转换工具更方便。

macb() ? lpcbyu(&gbcq/_\021%ocq\012\0_=w(gbcq)/_dak._=}_ugb_[0q60)s+转换之后得到:

main() { printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}这是1987年

国际C语言混乱代码大赛(The International Obfuscated C Code Contest, IOCCC)一等奖的获奖代码,由贝尔实验室的David Korn提交。当然平时我们不会写出这么复杂难懂的代码,但是分析这样的代码却可以扩展我们的知识。

int main()

{

/* unix被编译器内定为一个宏

* 相当于#define unix 1 */

printf("unix=%d\n", unix); /* =1 */

/* 打印字符串"un",因为"fun"是个字符数组

* "fun"+1相当于字符指针右移,指向"un" */

printf("%s\n","fun"+1);

/* "have"是个字符数组,"have"[1]即字符a

* 输出97,即第二个字符'a'的ASCII值。*/

printf("%d\n", "have"[1]);

printf("%d\n", 'a');

/* 在C语言中,x[1] = 1[x] */

printf("%d\n", (1)["have"]);

/* 97 - 96 = 0x61 - 0x60 = 1 */

printf("%d\n", (1)["have"] - 0x60);

/* 所以 "fun"+((1)["have"]-0x60) 相当于"fun"+1,输出"un" */

printf("%s\n", "fun" + ((1)["have"] - 0x60));

/* 将其中的1用unix代替 */

printf("%s\n", (unix)["have"]+"fun"-0x60);

/* 以上为后半部分 = "un" */

/* 下面两个都输出"bcde", 因为指针都是从'b'开始 */

printf("%s\n", "abcde" + 1);

printf("%s\n", &"abcde"[1]);

/* &"abcde"[1] == &(1)["abcde"] 输出一样 */

printf("%s\n", &(1)["abcde"]);

/* 1用unix代替 */

printf("%s\n", &unix["abcde"]);

/* 下面输出"%six" 并换行 */

printf("%s", &"?%six\n"[1]);

/* 注意:

\012 = 0x0a = \n,

第一个字符 \021 被跳过

\0 是空字符 */

/* 同样输出"%six" 并换行 */

printf("%s", &"\021%six\012\0"[1]);

/* 相当于这样 */

printf("%s", &unix["\021%six\012\0"]);

/* 把字符串"%six\n"当作格式,输出"ABix" */

printf(&unix["\021%six\012\0"], "AB");

/* 相当于这样 */

printf("%six\n", "AB");

/* 所以下面的可以输出"unix" */

printf("%six\n", (unix)["have"]+"fun"-0x60);

/* 至此,问题解决!!!输出"unix" */

printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);

return 0;

}

这段代码主要用到了x[a]和指针运算的一些知识,相信上面的步骤和注释已经很清楚了,最终结果就是输出unix。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值