C 的可变参数

1 可变参数的函数 

       最初,C中只有函数支持可变参数,例如最常见的printf系列函数,其声明如下:

#include <stdio.h>

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

int fprintf(FILE *stream, const char *format, ...);

int sprintf(char *str, const char *format, ...);

int snprintf(char *str, size_t size, const char *format, ...);

 

#include <stdarg.h>

int vprintf(const char *format, va_list ap);

int vfprintf(FILE *stream, const char *format, va_list ap);

int vsprintf(char *str, const char *format, va_list ap);

int vsnprintf(char *str, size_t size, const char *format, va_list ap);

要实现自己的支持可变参数的函数,需要用到下面几个宏:

#include <stdarg.h>

void va_start(va_list ap, last); /*功能:用可变参数前的最后一个参数last初始化ap*/

type va_arg(va_list ap, type); /*功能:返回ap后面type类型的参数*/

void va_end(va_list ap);     /*功能:终止ap使用*/

void va_copy(va_list dest, va_list src);/*功能:把src拷贝给dest*/

 

定义:

typedef char *va_list;

 

#define  _AUPBND                (sizeof (acpi_native_int) - 1)

#define  _ADNBND                (sizeof (acpi_native_int) - 1)

 

#define _bnd(X, bnd)            (((sizeof (X)) + (bnd)) & (~(bnd)))

#define va_arg(ap, T)           (*(T *)(((ap) += (_bnd (T,  _AUPBND))) - (_bnd (T,_ADNBND))))

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

#define va_start(ap, A)         (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))

 

其中,acpi_native_int定义为typedef s32acpi_native_int;typedef s64 acpi_native_int;

示例:实现自己的printf函数(转载)

void    print(char* fmt, ...)
{
    double vargflt = 0;
    int  vargint = 0;
    char* vargpch = NULL;
    char vargch = 0;
    char* pfmt = NULL;
    va_list vp;

    va_start(vp, fmt);
    pfmt = fmt;

    while(*pfmt)
    {
        if(*pfmt == '%')
        {
            switch(*(++pfmt))
            {
                case 'c':
                    vargch = va_arg(vp, int); 
                    /*    va_arg(ap, type), if type is narrow type (char, short, float) an error is given in strict ANSI
                        mode, or a warning otherwise.In non-strict ANSI mode, 'type' is allowed to be any expression. */
                    .....;
                    break;
                case 'd':
                case 'i':
                    vargint = va_arg(vp, int);
                    .......;
                    break;
                case 'f':
                    vargflt = va_arg(vp, double);
                    /*    va_arg(ap, type), if type is narrow type (char, short, float) an error is given in strict ANSI
                        mode, or a warning otherwise.In non-strict ANSI mode, 'type' is allowed to be any expression. */
                    .......;
                    break;
                case 's':
                    vargpch = va_arg(vp, char*);
                    .......;
                    break;
                case 'b':
                case 'B':
                    vargint = va_arg(vp, int);
                    ......;
                    break;
                case 'x':
                case 'X':
                    vargint = va_arg(vp, int);
                    ......;
                    break;
                case '%':
                    putchar('%');
                    break;
                default:
                    break;
            }
            pfmt++;
        }
        else
        {
            putchar(*pfmt++);
        }
    }
    va_end(vp);
}

后来,C99编译器既支持可变参数的函数,也支持可变参数的宏:


2 可变参数的宏

#define debug(fmt, …) printf(fmt,__VAR_ARGS__)     /*支持可变参数的宏*/

#define debug(fmt, …) printf(fmt,##__VAR_ARGS__)  /*支持可变参数的宏,其中可变参数可以为空*/

#define debug(fmt, arg…) printf(fmt,##arg)     /*GCC支持给可变参数一个名字,如arg 。当可变参数为空时,##操作使预处理器去除掉它前面的逗号*/

2.1 说明

<1> ...                          表示可变参数

<2> __VAR_ARGS__  保留名,将可变参数 ... 传给宏

<3> arg                       可变参数名,代表可变参数列表


2.2 示例

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

#define FMT_WARN(fmt...) do {if(0) printf(fmt);}while(0)

void _log(const char *domain, const char *file, const char *function, int line, int level, const char *fmt, ...)
{
        va_list arg;
 
        va_start(arg, fmt);
        
        printf("  domain: %s\n", domain);
        printf("    file: %s\n", file);
        printf("function: %s\n", function);
        printf("    line: %d\n", line);
        printf("   level: %d\n", level);
        vprintf(fmt, arg);
        
        va_end(arg);
}

#define log(dom,level,fmt...) do{                                   \
        FMT_WARN(fmt);                                                 \   /*说明:当fmt为空时,编译会出错*/
        _log(dom, __FILE__, __FUNCTION__, __LINE__, level, ##fmt);     \
}while(0)

#define log_rate(fmt, ...) ({                               \
             /*printf(fmt);*/                               \
             /*printf("%d -- %s -- %d\n",__VA_ARGS__);*/    \
             log(fmt, ##__VA_ARGS__);   \   /*说明:log_rate的参数fmt对应log的dom,可变参数 ... 与log的其他参数对应*/
        })


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值