龙跃十二

唯有坚韧者始能遂其志

C 语言的可变参数表函数的设计

大多数时候,函数中形式参数的数目通常是确定的,在调用时要依次给出与形式参数对应的所有实际参数。但在某些情况下希望函数的参数个数可以根据需要确定。典型的例子有大家熟悉的函数printf()、scanf()等

  可变参数的实现:
  C语言头文件stdarg.h提供了一个数据类型va-list和三个宏(va-start、va-arg和va-end),va—start使vp指向第一个可选参数。va—arg返回参数列表中的当前参数并使vp指向参数列表中的下一个参数。va—end把vp指针清为NULL。函数体内可以多次遍历这些参数,但是都必须以va—start开始,并以va—end结尾。用它们在
被调用函数不知道参数个数和类型时对可变参数表进行测试,从而为访问可变参数提供了方便且有效的方法。va-list是一个char类型的指针,当被调用函数使用一个
可变参数时,它声明一个类型为va-list的变量,该变量用来指向va-arg和va-end所需信息的位置。
下面给出va_list在C中的源码:  

     typedef char * va_list; 

  采用ANSI标准形式时,参数个数可变的函数的原型声明是: 

   type funcname(type para1, type para2, ...) 

  这种形式至少需要一个普通的形式参数,后面的省略号不表示省略,而是函数原型的一部分,type是函数返回值和形式参数的类型。

  调用者在实际调用参数个数可变的函数时,要通过一定的方法指明实际参数的个数,例如把最后一个参数置为空字符串。
  
  下面给出一个具体的例子:
求n个数的和:

int Sum(int n,...)
{
    int i = 0,sum = 0;
    va_list vp; 
    va_start(vp,n); //va—start使vp指向第一个可选参数
    for (i=0; i<n; i++)
    {
        sum +=va_arg(vp,int); 
    }
    va_end(vp); //va—end把vp指针清为NULLreturn sum;
}

printf函数实现(此处只实现了基本类型的打印)

void my_print(const char *format,...)
{
    char c = 0;
    va_list vp; 
    va_start(vp,format); //vp指向第一个可选参数
    while (*format)
    {
        c = *format;
        switch (c)
        {
        case '%':
            {
                char cc = *(++format);
                switch (cc)
                {
                case 'd':
                    {
                        char str[50];
                        int  n = va_arg(vp,int); //va—arg返回参数列表中的当前参数并使vp指向参数列表中的下一个参数。
                        char *string = _itoa(n,str,10); //把整数转为字符串
                        print_str(string);
                    }
                    break;
                case 'f':
                    {
                        char str[50];
                        double f = va_arg(vp,double);//va—arg返回参数列表中的当前参数并使vp指向参数列表中的下一个参数
                        char *string = _gcvt(f,10,str);//将浮点型数转换为字符串,取四舍五入
                        print_str(string);
                    }
                    break;
                case 'c':
                    putchar(va_arg(vp,char));
                    break;
                case 's':
                    {
                        char *string = va_arg(vp,char*);
                        print_str(string);
                    }
                    break;
                default:
                    break;
                }
            }
            break;
        default:
            putchar(c);
            break;
        }
        format++;
    }
    va_end(vp); //va—end把vp指针清为NULL。
}

要明白可变参数必须知道函数调用过程(栈帧的创建与销毁),此内容在前面的博文中有详细介绍,文章地址:函数调用过程

阅读更多
版权声明:本文为博主原创文章,转载请私信博主。 https://blog.csdn.net/qq_38646470/article/details/79238409
文章标签: 可变参数 C语言
个人分类: c语言
所属专栏: C语言
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

C 语言的可变参数表函数的设计

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭