C语言 可变参数 用法


前言

在C语言程序中我们涉及的最多的函数就是关于各种 level 的 log 输出的函数实现,这些函数基本都包括 printf() 以及相关的变形体。其中 printf() 的定义为

int printf(const char *format, ...);

该函数是最经典的可变参数函数,它除了有一个参数 format 固定的以外,后面的参数其个数和类型都是可变的,三个点 “…” 作为参数占位符。


一、ANSI C、GNU C

GNU计划,又称革奴计划,是由Richard Stallman在1983年9月27日公开发起的。它的目标是创建一套完全自由的操作系统。它在编写linux的时候自己制作了一个标准成为 GNU C标准。ANSI 美国国家标准协会,它对C做的标准ANSI C标准后来被国际标准协会接收成为 标准C 所以 ANSI C 和标准C(ISO C)是一个概念,其中目前出现的 C标准有:C89、C99、C11 。

总之,可以理解为:ANSI C与ISO C 对于我们开发者来说完全相同,GNU C在 ANSI C基础上增加了一些扩展(具体扩展可自行搜索),即理解为 ISO C == ANSI C < GNU C


二、可变参数宏

在 C99 标准之前,无法在宏定义中使用可变参数定义,C99之后可以通过__VA_ARGS__ 来代替可变参数,即省略号 “…” ,例如:

#define debug(format, ...) \
				printf(format, __VA_ARGS__)

在 GNC C 中,宏也可以接收可变数目的参数,就像使用函数一样,例如:

#define pr_debug(fmt,arg...) \  
				printk(KERN_DEBUG fmt, ##arg)

GNU C/CPP 还支持 ##__VA_ARGS__ ,其中 ## 操作将使预处理器去除掉它前面的那个逗号,因此可变参数宏还可以这样定义,

#define debug(format, ...)  \
				printf(format, ##__VA_ARGS__)

三、可变参数取参使用方法

1、先定义一个 va_list 类型的变量,比如 ptr,它指向参数列表的首地址;
2、用 va_start 宏初始化 ptr,它的第二个参数是第一个可变参数的前一个参数,即最后一个固定参数;
3、用 va_arg 返回可变的参数,它的第二个参数是要获取的变参类型;
4、可以通过反复调用 va_arg 来依次取得变参值;
5、最后用 va_end 宏结束可变参数的获取。
注意:
(1)定义的函数必须至少有一个固定的参数;因为需要通过固定参数来定位变参的首地址,也就是固定参数地址+sizeof(固定参数类型)
(2)固定参数和可变参数之间可以没有任何关系;虽然经典的printf函数中,第一个固定参数(格式化字符串)包含了后续变量参数的类型,但是这仅仅是函数功能的需要,语法上没有任何要求。

举例如下所示:

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

void variable_argument(int fix_argument1, ...)
{
    va_list ptr;

    va_start(ptr, fix_argument1);
    int first = va_arg(ptr, int);
    char *second = va_arg(ptr, char*);
    int third = va_arg(ptr, int);
    double four = va_arg(ptr, double);

    va_end(ptr);

    printf("first is %d, second is %s, third is %d, four is %f\n", first, second, third, four);

    return;
}

int main(int argc, char** argv[])
{
    variable_argument(1, 2, "hello", 5, 3.1415);
    return 0;
}

编译及运行结果如下:

yang@ubuntu:~$ gcc va_func.c 
yang@ubuntu:~$ ./a.out 
first is 2, second is hello, third is 5, four is 3.141500

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值