C语言可变参数简析

今天在看代码的时候,看到了这样一段调试的代码,搞不清楚(...)这个是什么意思,看了下相关资料,简单记录下。

#ifdef DEBUG
#define DBG(...) fprintf(stderr, " DBG(%s, %s(), %d): ", __FILE__, __FUNCTION__, __LINE__); fprintf(stderr, __VA_ARGS__)
#else
#define DBG(...)
#endif

1、printf代码

1

2

printf(“hello,world!”);其参数个数为1个。

printf(“a=%d,b=%s,c=%c”,a,b,c);其参数个数为4个。

如何编写可变参数函数呢?我们首先来看看printf函数原型是如何定义的。
在linux下,输入man 3 printf,可以看到prinf函数原型如下:

1

2

3

SYNOPSIS

#include <stdio.h>

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

后面的三个点...表示printf参数个数是不定的.
如何实现可变参数函数?
2. 编写可变函数准备
为了编写可变参数函数,我们通常需要用到<stdarg.h>头文件下定义的以下函数:

1

2

3

4

void va_start(va_list ap, last);

type va_arg(va_list ap, type);

void va_end(va_list ap);

void va_copy(va_list dest, va_list src);

其中:
va_list是用于存放参数列表的数据结构。

va_start函数根据初始化last来初始化参数列表。

va_arg函数用于从参数列表中取出一个参数,参数类型由type指定。

va_copy函数用于复制参数列表。

va_end函数执行清理参数列表的工作。

上述函数通常用宏来实现,例如标准ANSI形式下,这些宏的定义是:

1

2

3

4

5

typedef char * va_list; //字符串指针

#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )

#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )

#define va_end(ap) = (va_list)0 )

 使用宏_INTSIZEOF是为了按照整数字节对齐指针,因为c调用协议下面,参数入栈都是整数字节(指针或者值)。

4、用va_list实现vprintf()示例

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

void my_printf(const char *format, ...)
{
    int n;
    va_list arg_list;
    va_start(arg_list, arg_list);
    n = vprintf(format, arg_list);
    va_end(arg_list);
}

int main(int argc, char *argv[])
{
    int ai = 0;

    my_printf("%d\n", ai);

    return 0;
}

5、C语言可变参数函数简单实例

参数列表的格式是强制性参数在前,后面跟着一个逗号和省略号(...),这个省略号代表可选参数。
可变参数函数要获取可选参数时,必须通过一个类型为 va_list 的对象,它包含了参数信息。这种类型的对象也称为参数指针(argument pointer),它包含了栈中至少一个参数的位置。可以使用这个参数指针从一个可选参数移动到下一个可选参数,由此,函数就可以获取所有的可选参数。va_list 类型被定义在头文件 stdarg.h 中。

一个简单的例子,说明可变参数的用法

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

int simple(int num,...)        //num代表了要传递的可变参数的总数
{
        int i, result=0;
        va_list vl;     //va_list指针,用于va_start取可变参数,为char*
        va_start(vl,num);       //取得可变参数列表中的第一个值
        printf("num:%d, vl:%d\n",num,*vl);

        //访问所有赋给valist的值
        for (i = 0; i < (num-1); i++)//这里num表示可变参数列表中有多少个参数  
        {
              //这里把vl往后跳过4个字节(sizeof(int)大小)指向下一个参数,返回的是当前参数(而非下一个参数)
            result = va_arg(vl, int);  

            //这里打印下,可以看出,vl总是指向result后面的那个参数  
            printf("in for  result:%d,  *vl:%d\n", result, *vl);
        }
        va_end(vl);//结束标志  

        return result;
}

int main(int argc, char **argv)
{
        simple(5,1,2,3,4,5);

        return 0;
}

运行结果如下:

原文地址:http://www.runoob.com/cprogramming/c-variable-arguments.html

http://www.cnblogs.com/ThatsMyTiger/p/6924462.html

 https://www.cnblogs.com/edver/p/8419807.html

猜你喜欢

转载自blog.csdn.net/weixin_42445727/article/details/84071684
今日推荐