C语言学习-22-可变参数

一、前言

我们在用C语言实现一些功能时,例如:日志分级输出、字符串格式化写入CSV文件等,经常需要用到多个参数,且每次是不固定的参数个数,这就用到了头文件stdarg.h中的相关函数。

二、相关函数介绍

参考的是如下版本的相关头文件。

/usr/lib/gcc/x86_64-redhat-linux/4.8.2/include/stdarg.h

1、va_list

typedef __builtin_va_list __gnuc_va_list;

typedef __gnuc_va_list va_list;

va_list定义的是一个参数列表。

__builtin_va_list 没有写具体类型。

2、va_start

头文件中的定义:

#define va_start(v,l)   __builtin_va_start(v,l)

初始化可变参数列表va_list类型的v。l为最后一个固定参数的名称。

__builtin_va_start(v,l)没有具体实现。

例如函数声明为:

Status WriteData2Csv(FILE** FilePtr, char* StrFormat, ...)

这里的StrFormat就是l最后一个固定参数的名称。

man查看va_start定义:

void va_start(va_list ap, last);

va_start()宏初始化ap,以供va_arg()和va_end()后续使用,并且必须首先调用。
最后一个参数是变量参数列表之前的最后一个参数的名称,即调用函数的最后一个参数知道类型。
由于此参数的地址可以在 va_start() 宏中使用,因此不应将其声明为寄存器变量、函数或数组类型。

3、vsprintf

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

函数 vprintf(), vfprintf(), vsprintf(), vsnprintf() 分别等同于函数 printf(), fprintf(), sprintf(), snprintf(), 不同之处在于它们是用 va_list 而不是可变数量的参数调用的。 这些函数不调用va_end宏。
就是将ap(多个参数)按照format(例如:"%s%d%ld")格式化拼成字符串放入str中。

4、va_end

void va_end(va_list ap);

va_start()的每次调用都必须与同一函数中相应的 va_end()调用相匹配。va_end()可以是宏或
函数。

三、例子程序

1、WriteData2Csv

Status WriteData2Csv(FILE** FilePtr, char* StrFormat, ...)
{
    JudgeAllNullPointer(*FilePtr);
    JudgeAllNullPointer(StrFormat);

    char    WriteStr[WRITE_CSV_STR_LEN] = {0};
    va_list ParameterList;                        //定义参数列表

    va_start(ParameterList, StrFormat);           // 初始化可变参数列表ParameterList。StrFormat为最后一个固定参数的名称。
    vsprintf(WriteStr, StrFormat, ParameterList); // vsprintf使用参数列表ParameterList发送格式化StrFormat输出到字符串WriteStr。
    va_end(ParameterList);                        // 结束可变参数列表的访问,该宏va_end将ParameterList置为 NULL。

    //Log(WriteStr,Debug);
    fputs(WriteStr, *FilePtr);

    return SuccessFlag;
}

函数实现功能:将数据写入到CSV文件中。

    WriteData2Csv(FilePtr,"%s,%s,%s,%s,%d,%s,%d,%s,%d,%d,%d,%s,%s,%s,%s,%d,%s,%d,%s,%d,%s,%s,%s,%s,%s,%s\n",
            MBJ->TaskName,
            MBJ->ProcessName,
            MBJ->JobName,
            MBJ->JobDesc,
            MBJ->PhysicalJobsType,
            MBJ->PhysicalJobsName,
            MBJ->DomainNodeType,
            MBJ->DomainNodeName,
            MBJ->ScheduleJobPriority,
            MBJ->JobResourcesNum,
            MBJ->MaxParallelDegree,
            MBJ->ExecuteCalendar,
            MBJ->TimeStartCondition,
            MBJ->EstimatedRunTime,
            MBJ->EstimatedEndTime,
            MBJ->NodeDeathTransferFlag,
            MBJ->ReturnDefaultClassName,
            MBJ->RecordLog,
            MBJ->IndependentResourceName,
            MBJ->BreakPointFlag,
            MBJ->PreProcessingScripts,
            MBJ->PostProcessingScripts,
            MBJ->JobParameters,
            MBJ->ProcessDependencies,
            MBJ->GenerateEvent,
            MBJ->DependentEvent);

你可能感兴趣的:(#,C语言-学习,学习,c语言,开发语言)