Chinaunix首页 | 论坛 | 博客
  • 博客访问: 28126
  • 博文数量: 5
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 62
  • 用 户 组: 普通用户
  • 注册时间: 2013-08-27 15:18
个人简介

游戏!

文章分类

全部博文(5)

文章存档

2013年(5)

我的朋友

分类: C/C++

2013-08-31 13:23:44

对变参数,我个人认为它实现的两个根本理论基础:1.函数参数的入栈次序(C中参数是从左到右入栈)2.栈的增长方向。记住这两点。
第一个字符串是格式字符串。我定义的格式字符有c——显示字符、s——显示字符串。而且没有使用转义字符\



一、实际参数存放问题。

    现在开始看实现代码。调用函数是void myprint(const char * format, ...);函数中的三个英文字符点'.'代表其变量是变参的。在main函数中用了myprint("new printfcc fun!s", 'A', 'B', "YES")函数。现在看下编译器是怎么处理的。


    首先知道了参数入栈是从左到右进行的。就是说最先是字符串“new printfcc funl!s"的地址入栈(注意是地址), 然后是字符A入栈(入栈的是字符的ASCII值),字符B入栈,字符串”YES“的地址入栈。对C程序反汇编后得到下面的一段汇编代码。其中可以看到字符‘A’放在了0x4(%esp)中,‘B’放在了0x08(%esp)中——0x8加上esp中的值就是存放地址了
入栈地址 %esp 0x4(%esp)
0x8(%esp)
0xc(%esp)
值    格式字符串的地址 A的ASCII码(下面称第二个参数) B的ASCII码(第三个参数)
“YES"的地址(第四个参数)
    可以看到虽然字符A和B都只有一个字节,但是他们都占了四字节,这就是系统中的字节对齐问题。
    下面是main函数完整的汇编代码。



二、参数的显示问题

    在上面我们知道了各个参数的存放地址。现在使用就较方便了。format的值是第一个字符串参数的地址。&format就知道了格式字符串的入栈地址,(&format + 4)就是第二个参赛的存放地址。(ap = (char *)&(format) + 4)把参数A的地址以(char *)型赋值给ap.
    在while循环中对格式字符串中的值一个一个查看,若是遇到c或s就是后面找这个替代值(c、s是我定义的格式字符),是c就只要*ap就得到了这个字符,调用putchar显示既可。再ap加上4指向下一个参数。若是s,ap指向的地址内的值是要显示字符串的地址,想到了什么?指针的指针?对。用(char **)强制转换确定这个值就是指针的指针。然后取值后赋值给str去显示,这样就有了ap = (*(char **)ap)。格式字符查询完后,显示任务也就完成了。

三、后记

     用以上的方法实现变参数好像更透彻些,但是在stdarg.h这个头文件中有相关的宏可以直接调用实现变参。
 


阅读(1919) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~