您的位置:逆风者 VC++ 正文
 添加时间:2008-07-13 原文发表:2008-07-13 人气:141 来源:vckbase.net

本文章共3320字,分3页,当前第2页,快速翻页:
 
    0x1ffc-->a  (4字节)
    0x2000-->b  (4字节)
    0x2004-->c  (8字节)
    0x200c-->d  (4字节)
  对于函数void fun1(char a, int b, double c, short d)

  如果知道了参数a的地址,则要取后续参数的值则可以通过a的地址计算a后面参数的地址,然后取对应的值,而后面参数的个数可以直接由变量a指定,当然也可以像printf一样根据第一个参数中的%模式个数来决定后续参数的个数和类型。如果参数的个数由第一个参数a直接决定,则后续参数的类型如果没有变化并且是已知的,则我们可以这样来取后续参数, 假定后续参数的类型都是double;

逆风编程技术
void fun1(int num, ...)
{
    double *p = (double *)((&num)+1);
    double Param1 = *p;
    double Param2 = *(p+1);
    ...
    double Paramn  *(p+num);
}
  如果后续参数的类型是变化而且是未知的,则必须通过一个参数中设定模式来匹配后续参数的个数和类型,就像printf一样,当然我们可以定义自己的模式,如可以用i表示int参数,d表示double参数,为了简单,我们用一个字符表示一个参数,并由该字符的名称决定参数的类型而字符的出现的顺序也表示后续参数的顺序。 我们可以这样定义字符和参数类型的映射表,
i---int
s---signed short
l---long
c---char 
"ild"模式用于表示后续有三个参数,按顺序分别为int, long, double类型的三个参数那么这样我们可以定义自己版本的printf 如下
void printf(char *fmt, ...)
{
    char s[80] = "";
    int paramCount = strlen(fmt);
    write(stdout, "paramCount = " , strlen(paramCount = ));
    itoa(paramCount,s,10);
    write(stdout, s, strlen(s));
    char *p = (char *)(&fmt) + sizeof(char *);
    int *pi = (int *)p;
    for (int i=0; i<paramCount; i++)
    {
        char line[80] = "";
        strcpy(line, "param");
        itoa(i+1, s, 10);
        strcat(line, s);
        strcat(line, "=");
        switch(fmt[i])
        {
            case 'i':
            case 's':
                itoa((*pi),s,10);
                strcat(line, s);
                pi++;
                break;
            case 'c':
                {
                    int len = strlen(line);
                    line[len] = (char)(*pi);
                    line[len+1] = '\0';
                }
                break;
            case 'l':
                ltoa((*(long *)pi),s,10);
                strcat(line, s);
                pi++;
                break;
            default:
                break;
        }
    }
}
也可以这样定义我们的Max函数,它返回多个输入整型参数的最大值
int Max(int n, ...)
{
    int *p = &n + 1;
    int ret = *p;
    for (int i=0; i<n; i++)
    {
        if (ret < *(p + i))
            ret = *(p + i);
    }
    return ret;
}
可以这样调用, 后续参数的个数由第一个参数指定
int m = Max(3, 45, 12, 56);
int m = Max(1, 3);
int m = Max(2, 23, 45);

int first = 34, second = 45, third=5;
int m = Max(5, first, second, third, 100, 4);
结论

  对于可变参数函数的调用有一点需要注意,实际的可变参数的个数必须比前面模式指定的个数要多,或者不小于, 也即后续参数多一点不要紧,但不能少, 如果少了则会访问到函数参数以外的堆栈区域,这可能会把程序搞崩掉。前面模式的类型和后面实际参数的类型不匹配也有可能造成把程序搞崩溃,只要模式指定的数据长度大于后续参数长度,则这种情况就会发生。如:
 

本文章更多内容<<上一页 - 1 - 2 - 3 - 下一页>>
相关文章

通用 Thunk
VC6绘制3D饼状图 - 完美版
自定义控件—特效列表控件
直接调用类成员函数地址
Thunk 技术的一个改进
一个工业控制管道流动控件的实现
在C++中实现C#的delegate机制
强制编译时约束
VC6绘制3D饼状图
使用SNMP编辑(添加/删除/修改)ARP表
内存映射修改大文件
一个简单的外挂制作
动态加载CBitmapButton的四副状态图
一个支持各种交叉等形状工业控制管道控件的
利用模板元编程实现解循环优化
单件模式之土著人的可乐瓶
通过ODBC API实现对数据库的访问
七段数码显示的数字时钟
仿QQ悬挂窗口的实现
VC模仿超炫QQ界面的实现

相关评论


本文章所属分类:首页 VC++

  热门关键字: