• 函数不定参数个数的实现


    1. C语言函数的调用方式 _cdecl 调用

    _cdecl 是C Declaration的缩写(declaration,声明),表示C语言默认的函数调用方法:所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈所以在函数调用栈中, 越右边的参数在栈的越低端,既内存地址越大。

    2.实现

    函数如何实现不定参数:由于在C语言中没有函数重载,解决不定数目函数参数问题变得比较麻烦,即使采用C++,如果参数个数不能确定,也很难采用函数重载。对这种情况,提出了指针参数来解决问题。

    (1)va_list

      定义了一个指针arg_ptr, 用于指示可选的参数.

    (2)va_start(arg_ptr, argN)

      使参数列表指针arg_ptr指向函数参数列表中的第一个可选参数,argN是位于第一个可选参数之前的固定参数,

      或者说最后一个固定参数.如有一va 函数的声明是void va_test(char a, char b, char c, ...), 则它的固定参数依次是a,b,c, 最后一个固定参数argN为c, 因此就是va_start (arg_ptr, c).

    (3)va_arg(arg_ptr, type)

      返回参数列表中指针arg_ptr所指的参数, 返回类型为type. 并使指针arg_ptr指向参数列表中下一个参数.返回的是可选参数, 不包括固定参数.

    (4)va_end(arg_ptr)

      清空参数列表, 并置参数指针arg_ptr无效.

      (注:va在这里是variable-argument(可变参数)的意思.   这些宏定义在stdarg.h中,所以用到可变参数的程序应该包含这个头文件)

    过程:

    调用va_start()后parg将指向第一个不固定的参数,在这个函数中也就是v2后面的参数。

    接着调用va_parg():va_parg同样接受两个参数第一个参数是经过va_start()处理过后的parg指针。

    第二个参数是期望不固定参数的类型,编译器无法确定可变参数的类型,但是必须这么做。

    va_parg返回parg当前指向的那个可变的参数。并且每次调用都会更新这个指针,使得parg向下个参数移动;

    最后调用va_end():va_end接受一个参数,parg,他会将parg重置为NULL;没用调用va_end函数将无法运行。

    3.举例

    (1)固定参数个数(2个)

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdarg.h>
    
    int print(const char *format, ...)
    {
        va_list args;
        const char *args1;
        va_start(args, format);
        args1 = va_arg(args,const char *);
        va_end(args);
        printf("format=%s args1=%s", format, args1);
    }
    int main()
    {
        print("11111", "22222");
    }

    运行结果:

    format=11111 args1=22222

    (2)多个参数(采用循环)

    double average(double v1, double v2, ...){
        va_list parg;
        //将parg指向第一个不固定的参数
        va_start(parg, v2);
        double sum = 0.0;
        sum = v1 + v2;
        double value;
        int count = 2;
        //va_arg判断下一个不固定参数类型是否为double
        while((value = va_arg(parg, double)) != 0.0){
            sum += value;
            ++count;
        }
        va_end(parg);
        return sum/count;
     
    }


    4.注意

    va_arg(ap,type)中的type绝对不能为以下类型:
    ——char、signed char、unsigned char
    ——short、unsigned short
    ——signed short、short int、signed short int、unsigned short int
    ——float

    参考:

    https://www.cnblogs.com/linhaostudy/p/6695422.html

    https://blog.csdn.net/wabil/article/details/72800624?utm_source=blogxgwz0

    https://blog.csdn.net/bristar_zon/article/details/48465021

    https://blog.csdn.net/qq_25367755/article/details/50946574

  • 相关阅读:
    (CS模式)大学计算机基础考试系统
    四叶草的祝福
    做人的小故事!
    前天晚上回到北京了
    人生活的三种状态
    松口气了!
    Mysql一些基础用法
    云计算随想
    对vector与deque插值与遍历的性能数据
    gdb命令的常用调试选项
  • 原文地址:https://www.cnblogs.com/zzdbullet/p/9928078.html
Copyright © 2020-2023  润新知