今天在网上看到了一个C语言趣味小程序:打印自身代码。程序代码如下:

1
char*s="char*s=%c%s%c;main(){printf(s,34,s,34);}";main(){printf(s,34,s,34);}

程序的运行结果如下:

1
char*s="char*s=%c%s%c;main(){printf(s,34,s,34);}";main(){printf(s,34,s,34);}

输出结果和程序的源代码一样。是不是觉得这一段代码很神奇?让我们来分析一下这段“神奇”的代码。
首先我将源代码整理了一下,就变成了下面的这个样子:

1
2
3
4
5
char*s="char*s=%c%s%c;main(){printf(s,34,s,34);}";
main()
{
    printf(s,34,s,34);
}

第一行代码初始化一个字符串指针,指针指向了一个字符串常量的首地址。第四行代码调用printf函数。而就是这个printf函数输出了整个程序的源代码。

1
printf(s,34,s,34);

s在程序是什么呢?就是字符串 “char*s=%c%s%c;main(){printf(s,34,s,34);}” 的首地址。也就是说printf(s)就代表了printf(“char*s=%c%s%c;main() {printf(s,34,s,34);}”)。字符串里面有3个格式化输出的代码:%c %s %c。所以上面printf后面3个参数就是这几个格式化输出的值。

如果你调用

1
printf("%c",34)

程序将会打印出一个引号 ” 。

所以我们知道了这个打印自身的程序就是将程序的源代码保存在一个字符串中,然后在输出函数中打印这个字符串,由于源代码中char *s = 后面有引号和printf函数中的引号有冲突,不能直接输出,于是程序就通过printf函数的%c打印32打印出了引号。

整个程序的原理就是这样,关键点在字符串s中的%c%s%c。当然在我的C-Free中上面的代码无法编译成功。因为缺少头文件。于是我稍稍修改了一下源代码,成了下面这样:

1
2
3
#include <stdio.h>
char*s="#include <stdio.h>%cchar*s=%c%s%c;main(){printf(10,s,34,s,34);}";
main(){printf(s,10,34,s,34);}

看我关于换行符的处理,我没有直接输出”\n”,而是使用%c打印它的ascii值10。你想知道为什么吗?自己动手写代码吧。:)

(全文完)

更多新手学习C语言的经验请看:http://dabentu.com/1123.html