LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1109|回复: 6

一个有趣的程序

[复制链接]
发表于 2005-8-26 20:53:50 | 显示全部楼层 |阅读模式
#include <stdio.h>
   void main(a)
  {
     printf(a,34,a="main(a){printf(a,34,a=%c%s%c,34);}",34);
   }
   哪位解释一下
发表于 2005-8-26 21:22:56 | 显示全部楼层
Post by batiestuta
#include <stdio.h>
   void main(a)
  {
     printf(a,34,a="main(a){printf(a,34,a=%c%s%c,34);}",34);
   }
   哪位解释一下

嗯,有点意思.
其实很简单啦,因为缺乏类型检查,所以本来是整型的a就可以用来做char*
这个函数所做的事情就是,将 34(其实就是双引号)压栈,将"main(a){printf(a,34,a=%c%s%c,34);}"字符串地址赋给a,然后将a压栈,最后将 34 , a 压栈,想想栈里面现在有什么? 一个format string的地址a,一个字符34作为printf的第二个参数,然后又是一个string的地址,然后又是一个字符34,所以printf就做下面的事情:输出 main(a){printf(a,34,a= 然后读第二个参数,发现是34(双引号),就打印出",然后再读第三个参数,是个string的地址,就打印出 main(a){printf(a,34,a=%c%s%c,34);},继续读第四个参数,也是34,又输出一个双引号",如此而已.
回复 支持 反对

使用道具 举报

发表于 2005-8-26 22:10:42 | 显示全部楼层

  1. 0x08048398 <main+0>:    push   %ebp
  2. 0x08048399 <main+1>:    mov    %esp,%ebp
  3. 0x0804839b <main+3>:    sub    $0x8,%esp
  4. 0x0804839e <main+6>:    and    $0xfffffff0,%esp
  5. 0x080483a1 <main+9>:    mov    $0x0,%eax
  6. 0x080483a6 <main+14>:   add    $0xf,%eax
  7. 0x080483a9 <main+17>:   add    $0xf,%eax
  8. 0x080483ac <main+20>:   shr    $0x4,%eax
  9. 0x080483af <main+23>:   shl    $0x4,%eax
  10. 0x080483b2 <main+26>:   sub    %eax,%esp
  11. [b]0x080483b4 <main+28>:   movl   $0x80484f8,0x8(%ebp)
  12. 0x080483bb <main+35>:   mov    0x8(%ebp),%eax
  13. 0x080483be <main+38>:   push   $0x22
  14. 0x080483c0 <main+40>:   pushl  0x8(%ebp)
  15. 0x080483c3 <main+43>:   push   $0x22
  16. 0x080483c5 <main+45>:   push   %eax
  17. 0x080483c6 <main+46>:   call   0x80482b8 <_init+56>
  18. [/b]0x080483cb <main+51>:   add    $0x10,%esp
  19. 0x080483ce <main+54>:   leave  
  20. 0x080483cf <main+55>:   ret   

复制代码


好像是先把字符串赋给a,再完成压栈操作.
其实等同于这个,这样就容易理解了.
printf("main(a){printf(a,34,a=%c%s%c,34);}",34,"main(a){printf(a,34,a=%c%s%c,34);}",34);
回复 支持 反对

使用道具 举报

发表于 2005-8-27 08:19:40 | 显示全部楼层
Post by 弥敦路九号

好像是先把字符串赋给a,再完成压栈操作.

呵呵,我有点想当然了,其实这只是编译器的实现问题.
把赋值先做从逻辑上确实好一点.
Post by 弥敦路九号

其实等同于这个,这样就容易理解了.
printf("main(a){printf(a,34,a=%c%s%c,34);}",34,"main(a){printf(a,34,a=%c%s%c,34);}",34);

好是好一点,只是这个程序的精髓就没有了 ;)
回复 支持 反对

使用道具 举报

发表于 2005-8-27 09:35:16 | 显示全部楼层
嗯。 开始乍一看还真是让人有点蒙。
回复 支持 反对

使用道具 举报

发表于 2005-8-28 22:46:44 | 显示全部楼层
这个程序所做的就是打印自身,论坛以前有讨论的。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-8-29 12:55:17 | 显示全部楼层
明白了,主要是编译器里实现的函数参数入栈的顺序,是以reverse order压入栈中的。
回复 支持 反对

使用道具 举报

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

本版积分规则

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