QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 1105|回复: 3

看看我对一段怪异程序的分析(我头晕了整整两百圈!)

[复制链接]
发表于 2004-3-13 22:16:13 | 显示全部楼层 |阅读模式
这是源程序
main(v,c)char**c;{for(v[c++]="hello,world!\n";
(!!c)[*c]&&(v--||--c&&execlp(*c,*c,c[!!c]+
!!c,!c));**c=!c)write(!!*c,*c,!!**c);}

----------1985年 HP Jack Applin 所写.

以下是我的分析

请不要小看这段程序,我研究了半天终于看出点名堂了,不过看的头疼不想再往下看了,我把思路写出来,如果谁愿意去研究只要有耐心可以得出结果的。
首先把程序整理一下
代码:
[code:1]
main(v,c)
char**c;
{
   for(v[c++] = "hello, world!\n";  (!!c)[*c] && (v-- || --c && execlp(*c, *c, c[!!c]+ !!c,!c)); **c = !c)
      write(!!*c,*c,!!**c);
}
[/code:1]


下面我把主要的给讲一下让大家自己去思考
首先注意第一个地方

v[c++]

其实v[c++]可以写成这种形式(c++)[v],如果忽略++其实就是c[v],这样不知道能不能理解了,其实种形式用下面这个例子就好理解了

char *argv[] = {"zhang", "xin", "hua"};

这里可以先考虑argv[0],这个我想就不用我解释了吧,学过C的人应该都明白这是什么意思,明白了argv[0]就可以把他改成0[argv]形式,也就是说argv[0] 和0[argv]是等价的,这又如何理解呢,我在举个简单的例子,可以考虑100+0和0+100,是不是应该恍然大悟了?这就是问题的关键所在,同理100+2==2+100这是在也简单不过的等式了。好了这里我就不罗嗦留给大家自己去思考了。

再考虑下面重点

(!!c)[*c]

这里其实和上边大同小异只不过有点弯需要转过来,首先是(!!c)这里很容易迷惑人,其实只要c不为空,(!!c)的结果就是1,也就是说(!!c)[*c]可以写成1[*c]的形式看懂了上边的这也就不难理解了,只不过这里的*c指向了下级指针,而1[*c]其实就是取字符串的第二个字符,如果字符串的内容为空,那么就可以退出for循环了。好了接着往下看

execlp(*c, *c, c[!!c]+ !!c,!c));

这才是程序的精华所在,也是最为复杂的地方,其实这里我也只是分析了这个语句的作用,这个语句的基本作用就是递归调用上面的这个程序,至于为什么会递归调用就留给大家自己去思考吧,因为思考量太大我也没有耐心再往下想了,还是留给大家去考虑吧至于最后一句写函数就不用我说了吧,其实就是朝屏幕上打印字符串,至于到底打印什么字符串也留给大家自己去思考吧

如果想考虑这段程序还要考虑下面的问题
char *str[] = {"zhang", "xin", "hua"};
0[str] = "hello";
printf("%s\n", str[0]);
想想结果是什么
 楼主| 发表于 2004-3-14 14:07:22 | 显示全部楼层
今天早上起来又有了精神头,继续把这段程序给分析完了,下面是我对这断程序的改进和简化
代码:


#include <stdio.h>
#include <unistd.h>

[code:1]
main&#40;int v, char **c&#41;
&#123;
   char hello&#91;&#93; = &quot;hello world!\n\n&quot;;

   for&#40;v&#91;c&#93; = hello; 1&#91;*&#40;c+1&#41;&#93;&amp;&amp;&#40;v--||execlp&#40;*c, *c, c&#91;1&#93;+1, NULL&#41;&#41;; 0&#91;*&#40;c+1&#41;&#93; = 0&#41;
      write&#40;1,  0&#91;&#40;c+1&#41;&#93;, 1&#41;;
&#125;
[/code:1]

在LINUX下用GCC3.2编译通过,别看这断小程序折腾的我不轻,有兴趣的朋友琢磨琢磨,呵呵
回复

使用道具 举报

 楼主| 发表于 2004-3-14 18:01:51 | 显示全部楼层
这是我分解过的程序

[code:1]
hello&#40;int argc, char *argv&#91;&#93;&#41;
&#123;
        char hello&#91;&#93; = &quot;hello world!\n &quot;;
        char *c = *&#40;argv + 1&#41; + 1;

        argv&#91;argc&#93; = hello;

        while&#40;*c&#41;
        &#123;
                if&#40;argc--&#41;
                        write&#40;1, *&#40;argv+1&#41;, 1&#41;;
                else &#123;
                        execlp&#40;*argv, *argv, *&#40;argv+1&#41; + 1, NULL&#41;;
                        break;
                &#125;
                **&#40;argv+1&#41; = 0;
        &#125;
&#125;

main&#40;int argc, char *argv&#91;&#93;&#41;
&#123;
        char *str&#91;argc+1&#93;;

        memcpy&#40;str, argv, sizeof&#40;str&#41;-4&#41;; /*防址缓冲区溢出产生异常*/
        hello&#40;argc, str&#41;;
&#125;
[/code:1]
回复

使用道具 举报

发表于 2004-3-15 09:05:36 | 显示全部楼层
强啊,我已经晕死,我要休息。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-9-29 11:30 , Processed in 0.068677 second(s), 16 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表