bierdaci 发表于 2004-3-13 22:16:13

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

这是源程序
main(v,c)char**c;{for(v="hello,world!\n";
(!!c)[*c]&&(v--||--c&&execlp(*c,*c,c[!!c]+
!!c,!c));**c=!c)write(!!*c,*c,!!**c);}

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

以下是我的分析

请不要小看这段程序,我研究了半天终于看出点名堂了,不过看的头疼不想再往下看了,我把思路写出来,如果谁愿意去研究只要有耐心可以得出结果的。
首先把程序整理一下
代码:

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);
}



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

v

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

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

这里可以先考虑argv,这个我想就不用我解释了吧,学过C的人应该都明白这是什么意思,明白了argv就可以把他改成0形式,也就是说argv 和0是等价的,这又如何理解呢,我在举个简单的例子,可以考虑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 = "hello";
printf("%s\n", str);
想想结果是什么

bierdaci 发表于 2004-3-14 14:07:22

今天早上起来又有了精神头,继续把这段程序给分析完了,下面是我对这断程序的改进和简化
代码:


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


main&#40;int v, char **c&#41;
{
   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;;
}


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

bierdaci 发表于 2004-3-14 18:01:51

这是我分解过的程序


hello&#40;int argc, char *argv&#91;&#93;&#41;
{
        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;
        {
                if&#40;argc--&#41;
                        write&#40;1, *&#40;argv+1&#41;, 1&#41;;
                else {
                        execlp&#40;*argv, *argv, *&#40;argv+1&#41; + 1, NULL&#41;;
                        break;
                }
                **&#40;argv+1&#41; = 0;
        }
}

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

        memcpy&#40;str, argv, sizeof&#40;str&#41;-4&#41;; /*防址缓冲区溢出产生异常*/
        hello&#40;argc, str&#41;;
}

jingyu 发表于 2004-3-15 09:05:36

强啊,我已经晕死,我要休息。 :cry:
页: [1]
查看完整版本: 看看我对一段怪异程序的分析(我头晕了整整两百圈!)