根据前面的某一篇的文章,可以清楚的看到:对于每一个函数,通过这个函数的[ebp+x]就可以直接访问到它调用的时候传进来的形参的值,通过[ebp-x]就可以直接访问它的局部变量。

所以printf这个函数不定参数的实现是通过栈机制实现的,在传入实参的时候,从右向左一次把各个参数压入栈,但是这些压入栈的数据是没有类型区分的,就是把相应的数据依次放到栈中排好。最后压入栈的那个参数“%d%d%d”等类似的参数,才是决定printf参数类型的东西。等到程序的执行控制权到达printf中以后,printf就从传入的实参的起始位置,按照“%d%d%d”等类似的字符串来控制类型依次输出。这个字符串控制输出的个数和类型。同时这个字符串没有越界检测。

int a = 10;
printf("%d %d %d\n", a);

  这种打印的越界是不会检测的,函数调用前实参压栈a,然后压栈"%d %d %d\n"类型控制字符串。最后在printf中函数调用的时候,从之前压入的实参中依次打印出三个int,虽然压入栈的实参只有一个int,但是没有越界检测,所以还是会打印三个int。

来分析一个实际的问题:

char s[] = "123", *p;
p = s;
printf("%c%c%c\n", *p++, *p++, *p++);

  这个问题要注意printf和*p++这两个知识点,printf的参数压栈是从右向左的,并且注意*p++的执行顺序。所以第一个压栈的参数是1然后压栈2,然后压栈3。打印的时候一次打印321。

最新文章

  1. Golang汇编命令解读
  2. .net 一些开源的东东
  3. 【转】CSRF攻击的应对之道
  4. Java中的代理模式
  5. COURSES(poj 1469)
  6. 从cocos2dx中寻找函数指针传递的方法
  7. 各大搜索引擎的User-Agent
  8. BZOJ2741: 【FOTILE模拟赛】L
  9. sql第二天
  10. MySQL技巧(一)
  11. Dockerfile基础
  12. 【Linux】常见公共DNS地址
  13. Future、 CompletableFuture、ThreadPoolTaskExecutor简单实践
  14. Oracle 基础学习笔记
  15. h5内容超出可以滑动展示的处理,iscroll的使用
  16. spring boot 2.0 与FASTDFS进行整合
  17. Database Vault Administrator的使用
  18. centos7 端口转发
  19. linux系统编程之信号(五):信号集操作函数,信号阻塞与未决
  20. Paxos算法的通俗理解(转)

热门文章

  1. Hibernate get 和load的区别
  2. net-ldap for ruby openNebula ldap
  3. C#生成PDF
  4. VIM中格式化json
  5. GWT RPC机制
  6. collectionView 中cell间距设置建议
  7. C# XML与Json之间相互转换
  8. Java 注解机制
  9. 百度apistore第三方登陆
  10. Java基础之垃圾回收