C语言——可变参数

什么是可变参数

        在C语言编程中,我们会遇到一些参数数量可变的函数,如printf() scanf()……

函数原型为

int printf(const char* format,…)

int scanf(const char *format,…)

        在这些函数中,除了参数format固定外,还存在"..."占位符,后面的参数类型与数量都是可变的

含可变参数的函数参数列表

在任何一个含可变参数的函数中,它们都有两个部分:

        一是固定参数至少要有一个固定参数,其声明与普通函数参数声明相同;

        另一个是可选参数,可选参数由于数目不定(0个或以上),声明时用"…"表示。

固定参数和可选参数共同构成可变参数函数的参数列表。

怎么实现可变参数

        C语言中使用va_list系列变参宏实现变参函数,此处va意为variable-argument(可变参数)。

        <stdarg.h>

//
// stdarg.h
//
//      Copyright (c) Microsoft Corporation. All rights reserved.
//
// The C Standard Library <stdarg.h> header.
//
#pragma once
#define _INC_STDARG

#include <vcruntime.h>

#pragma warning(push)
#pragma warning(disable: _VCRUNTIME_DISABLED_WARNINGS)

_CRT_BEGIN_C_HEADER



#define va_start __crt_va_start
#define va_arg   __crt_va_arg
#define va_end   __crt_va_end
#define va_copy(destination, source) ((destination) = (source))



_CRT_END_C_HEADER

#pragma warning(pop) // _VCRUNTIME_DISABLED_WARNINGS
typedef char * va_list;
 
// 把 n 变为 sizeof(int) 的倍数
#define _INTSIZEOF(n)       ( (sizeof(n)+sizeof(int)-1) & ~(sizeof(int)-1) )
 
// 初始化 ap 指针,使其指向第一个可变参数。v 是可变参数列表的前一个参数
#define va_start(ap,v)      ( ap = (va_list)&v + _INTSIZEOF(v) )
 
// 该宏返回当前可变参数值,并使 ap 指向列表中的下个可变参数
#define va_arg(ap, type)    ( *(type *)((ap += _INTSIZEOF(type)) - _INTSIZEOF(type)) )
 
// 将指针 ap 置为无效,结束可变参数的获取
#define va_end(ap)          ( ap = (va_list)0 )

 代码示例

#include <stdarg.h>
#include <stdio.h>


int sum(int n, ...)//n为参数个数
{
    int i, sum = 0;
    va_list vap;        //定义参数列表,vap为可变参数类型

    va_start(vap, n);   //初始化参数列表
    for (i = 0; i < n; i++)
    {
        sum += va_arg(vap, int);//va_arg()获取 n 后面每一个参数的值; 获取值的类型
    }
    va_end(vap);//收尾工作

    return sum;
}

int main()
{
    printf("%d", sum(3, 1, 23, 4));

    return 0;
}

注意

va_arg(ap, type)宏中的 type 不可指定为以下类型:

  • char
  • short
  • float

在C语言中,调用不带原型声明或声明为变参的函数时,主调函数会在传递未显式声明的参数前对其执行缺省参数提升(default argument promotions),将提升后的参数值传递给被调函数。

​提升操作如下:

  • float 类型的参数提升为 double 类型
  • char、short 和相应的 signed、unsigned 类型参数提升为 int 类型
  • 若 int 类型不能容纳原值,则提升为 unsigned int 类型
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值