C语言变参的实现

来源:互联网 发布:淘宝拍卖手表骗局揭秘 编辑:程序博客网 时间:2024/04/19 15:30

今天本来想定位下项目中日志打印部分的错误,尝试在变参的个数匹配不上时,编译给出warning或error,可惜弄了半天也没实现。

个人测试实现的变参函数代码如下,虽是测试代码,但也基本写明了变参的实现过程,需要注意的问题和相关要点都写在注释中了,下面上代码。

如果有哪位大侠能够给出我上面提到的warning和error的生成建议,欢迎留言或给我私信交流。废话少说,上代码了,可以直接g++ variable_arg.cpp编译成功。

/*  * File:   variable_arg.cpp * Author: Carl * * Created on August 28, 2012, 5:25 PM */#include <cstdlib>#include <cstdio>#include <stdarg.h>#include <cstring>using namespace std;/* * 1)C标准规定实现可变参数机制的函数至少要有一个固定参数。 * 2)隐式类型不可用。例如,va_arg指定了类型是double,若传入的是int类型的变量10,就会报错 * 3)C语言的整型提升原则。也就是说,在va_arg中获取float和double使用的type是double,而获取char,short和int使用的type是int * 4)函数指针不可用,除非用typedef定义过 */void miniprintf(const char *fmt, ...){    va_list ap; //声明一个对象,用来盛放参数,一个char链表(实际应该是一个连续的内存块,像数组一样),表现为一个指向char类型的指针    int d;    char c, *p, *s;    double f;    //初始化va_list,通过最后的固定参数实现对可变参数初始位置的定位,并未va_list分配内存,将可变参数复制到该内存块中,是va_list指向给内存块的初始位置    va_start(ap, fmt); //ap指向第一个(不是第0个)参数,fmt后面的那个    while (*fmt)    {        if (*fmt != '%') //普通字符直接输出        {            putchar(*fmt++);            continue;        }        fmt++; //格式化字符,++指向s,d之类的格式字符位        switch (*fmt++) //此处的++,目的是指向格式字符位的下一位,为下次loop准备        {            //根据相应格式来取到对应的匹配参数        case 's':            //va_arg,通过移动指针va_list获取由参数type(第二个参数)指定的变量,并返回该变量            s = va_arg(ap, char *);            printf("%s", s);            break;        case 'd':            d = va_arg(ap, int);            printf("%d", d);            break;        case 'c':            c = (char) va_arg(ap, int);            printf("%c", c);            break;        case 'f':            f = va_arg(ap, double);            printf("%f", f);            break;        default: //不被支持的格式字符            printf("the format [%c] is not supported", *fmt);            break;        }    }    va_end(ap); //这个最好都要调用一次,在有的C实现中,可能用来释放va_start为va_list分配的内存    return;}double sum(int lim, ...){    va_list ap;    double total = 0;    int i;    va_start(ap, lim);    for (i = 0; i < lim; i++)    {        total += va_arg(ap, double); //依次取到每个参数    }    va_end(ap);    return total;}int main(int argc, char** argv){    char str[10];    memset(str, 0, sizeof (str));    memcpy(str, "hello", 5);    miniprintf("this is the string \"%s\", \nthis is the int %d, \nthis is the character %c\n", str, 3, 'a');    double total = 0;    total = sum(5, 10.0, 20.0, 30.0, 40.0, 50.0);       //这里如果是10,20这种int型的数据,会得到错误的结果    miniprintf("total is %f\n", total);    return 0;}

运行结果如下

this is the string "hello", this is the int 3, this is the character atotal is 150.000000

水平有限,如果有朋友发现错误,欢迎留言交流。

转载请保留本文链接,如果觉得我的文章能帮到您,请顶一下。,谢谢。


原创粉丝点击