概述

  • 某种情况下,我们可能需要一个具有可变参数的函数,C语言提供了一种标准的实现可变参数的方法
  • C语言实现可变参数的方案是基于标准库<stdarg.h>的
  • 可变参数的类型
    • 可变参数可以放在一个集合中,可以使用指针类型的参数或引用类型的参数来实现可变参数
    • 可变参数不可以放到一个集合中,可以使用C语言提供的标准方案来实现可变参数

标准库 stdarg.h

  • stdarg.h中定义的内容

    • 一个类型

      • va_list,用来定义存放参数列表
    • 三个宏(用于获取参数个数未知的函数中的参数)
      • void va_start(va_list ap, last_arg)

        • 通常与 va_arg 和 va_end 配合使用,且必须在 va_arg 和 va_end 之前被调用
        • va_start 初始化 ap 变量(为 ap 变量分配内从空间),last_arg 为传递给函数的已知的固定参数列表中的最后一个。
        • ap变量用来存储通过 va_arg 获取额外参数时所必需的信息
      • type va_arg(va_list ap, type)
        • 检索函数参数列表中类型为 type 的下一个参数
      • void va_end(va_list ap)
        • 允许使用了 va_start 宏 的 带有可变参数的函数 返回,若函数返回之前没有调用 va_end,则函数返回的结果是未定义的

实现方案

  • 形式

    • 实现可变参数的函数的参数列表通常包括以下两部分

      • 固定参数列表,通常包含可变参数的总个数信息(通常为固定参数列表中的最后一个参数,即省略号'...'前的那个参数)
      • 可变参数列表,使用省略号'...'表示
  • 步骤

    • 定义一个函数,最后一个参数为省略号'...',且省略号前的那个参数总是int类型,表示参数的总个数
    • 在函数定义中创建 va_list 类型变量,用来存储通过 va_arg 获取额外参数时所必需的信息
    • 使用 int 参数和 va_start 宏来初始化 va_list 变量为一个参数列表
    • 使用 va_arg 宏和 va_list 变量来访问参数列表中的每个项
    • 使用宏 va_end 来清理赋予 va_list 变量的内存
  • 示例

    // 计算可变数量个参数的和
    int sum(int num, ...) {
    // 定义va_list类型变量
    va_list valist;
    int i;
    double sum = 0.0;
    // 初始化valist
    va_start(valist, num);
    // 获取参数列表中的每个项
    for (i = 0; i < num; i++) {
    sum += va_arg(valist, int);
    }
    // valist变量的内存
    va_end(valist);
    return sum;
    }
    // 实现可变参数的函数的使用示例
    int main(int argc, const char * argv[]) {
    printf("Sum of 4, 5, 6, 7 = %d\n", sum(4, 4, 5, 6, 7));
    printf("Sum of 3, 6, 9 = %d\n", sum(3, 3, 6, 9));
    return 0;
    }

C语言-11-可变参数的实现方案的更多相关文章

  1. [11 Go语言基础-可变参数函数]

    [11 Go语言基础-可变参数函数] 可变参数函数 什么是可变参数函数 可变参数函数是一种参数个数可变的函数. 语法 如果函数最后一个参数被记作 ...T ,这时函数可以接受任意个 T 类型参数作为最 ...

  2. C语言的可变参数在Linux(Ubuntu)与Windows下注意点

    基本上C语言的可变参数原理在不同平台和不同编译器下基本类似(通过函数入栈,从右向左,从高位到低位地址),不过部分实现会有所不同:在使用中需要注意的是: va_list 为char 类型指针,部分调用如 ...

  3. C语言中可变参数的函数(三个点,“...”)

    C语言中可变参数的函数(三个点,“...”) 本文主要介绍va_start和va_end的使用及原理. 在以前的一篇帖子Format MessageBox 详解中曾使用到va_start和va_end ...

  4. C++ 11可变参数接口设计在模板编程中应用的一点点总结

    概述 本人对模板编程的应用并非很深,若要用一句话总结我个人对模板编程的理解,我想说的是:模板编程是对类定义的弱化. 如何理解“类定义的弱化”? 一个完整的类有如下几部分组成: 类的名称: 类的成员变量 ...

  5. C语言中可变参数的原理——printf()函数

    函数原型: int printf(const char *format[,argument]...) 返 回 值: 成功则返回实际输出的字符数,失败返回-1. 函数说明: 使用过C语言的人所再熟悉不过 ...

  6. C语言中可变参数函数实现原理

    C函数调用的栈结构 可变参数函数的实现与函数调用的栈结构密切相关,正常情况下C的函数参数入栈规则为__stdcall, 它是从右到左的,即函数中的最右边的参数最先入栈.例如,对于函数: void fu ...

  7. C语言中可变参数的用法

    原文地址: http://blog.csdn.net/wooin/archive/2006/04/29/697106.aspx   我们在C语言编程中会遇到一些参数个数可变的函数,例如printf() ...

  8. C语言函数可变参数列表

    C语言允许使用可变参数列表,我们常用的printf函数即为可变参数函数,C标准库提供了stdarg.h为我们提供了这方面支持:该头文件提供了一些类型和宏来支持可变参数列表,包括类型va_list,宏v ...

  9. c++11——可变参数模板

    在c++11之前,类模板和函数模板只能含有固定数量的模板参数,c++11增加了可变模板参数特性:允许模板定义中包含0到任意个模板参数.声明可变参数模板时,需要在typename或class后面加上省略 ...

随机推荐

  1. codeforces C. Design Tutorial: Make It Nondeterministic

    题意:每一个人 都有frist name 和 last name! 从每一个人的名字中任意选择 first name 或者 last name 作为这个人的编号!通过对编号的排序,得到每一个人 最终顺 ...

  2. react native之组织组件

    这些组件包括<TabView>,<NavigatorView>和<ListView>,他们实现了手机端最常用的交互和导航.你会发现这些组件在实际的项目中会非常有用. ...

  3. Screensiz.es – 最流行移动设备及显示器的屏幕规格大全

    Screensiz.es 帮助您快速找到目前市场上最流行的设备和显示器的屏幕规格.尺寸数据来自维基百科,使用更好理解的像素密度.流行度推算自 Google 查询(从 AdWords 流量估算),以及一 ...

  4. [Python]同是新手的我,分享一些经验

    本来想分享一些知识,但是发现,写着写着,感觉分享一些经验,或许会少让大家走一些弯路,索性就把标题一改. 我不是教给大家些什么,我没有资格,我也是摸着石头过河,我只是本着分享的精神,在这里分享自己的东西 ...

  5. Scrum1.2--spring计划

    项目功能--深入分析  燃尽图

  6. POI中getLastRowNum() 和getLastCellNum()的区别 hssfSheet.getLastRowNum();//最后一行行标,比行数小1 hssfSheet.getRow(k).getLastCellNum();//获取列数,比最后一列列标大1

    hssfSheet.getLastRowNum();//最后一行行标,比行数小1 hssfSheet.getRow(k).getLastCellNum();//获取列数,比最后一列列标大1

  7. TinyOS和Deluge的安装模拟(一)

    介绍 TinyOS是一款嵌入式操作系统,相信做无线传感器网络开发的同志们都不陌生.同类型的系统有不少,但是TinyOS的应用较之其他系统更为广泛.TinyOS 1.x版本和2.x版本是目前主要的两个分 ...

  8. 【Win10】使用 ValidationAttribute 实现数据验证

    WPF 中数据验证的方式多种多样,这里就不说了.但是,在 Windows Phone 8.1 Runtime 中,要实现数据验证,只能靠最基础的手动编写条件判断代码来实现.如果用过 ASP.NET M ...

  9. 常用的android弹出对话框

    我们在平时做开发的时候,免不了会用到各种各样的对话框,相信有过其他平台开发经验的朋友都会知道,大部分的平台都只提供了几个最简单的实现,如果我们想实现自己特定需求的对话框,大家可能首先会想到,通过继承等 ...

  10. jQuery的事件click

    不管是在asp.net 还是asp.net mvc中,对象的click事件是我们最常用到的一个事件,说明用户click点击一下mouse的左键,铵下并放开的事件. 今天已经是十一月份了,学习又是新的开 ...