可变参数__VA_ARGS__ 、 va_start、va_arg、valist 简单使用

 1. 调试功能一般会使用到宏+可变参数的方式

1.1

 ##__VA_ARGS__      之详细解析

 

例如:

case A.

#define my_print1(...)    printf(__VA_ARGS__)   

my_print1("i=%d,j=%d\n",i,j)  正确打印

 

case B.

#define my_print2(fmt,...)  printf(fmt, __VA_ARGS__)  

my_print1("i=%d,j=%d\n",i,j) 

正确打印

my_print2("iiiiiii\n")       

编译失败,因为扩展出来只有一个参数,至少要两个及以上参数

 

case C.

#define my_print2(fmt,...)  printf(fmt, ##__VA_ARGS__)  

my_print1里面不管是几个参数都能正确打印

宏前面加上##的作用在于,当可变参数的个数为0时,这里的##起到把前面多余的","去掉的作用,否则会编译出错

 

#define MODULE_NAME     "MY_LIBS"
#define log_e(fmt, ...)  printf("[ERROR]["MODULE_NAME"](%s|%d)"fmt,__func__,__LINE__,##__VA_ARGS__)

#include <stdio.h>


#define MODULE_NAME      "MY_LIBS"

#define log_e(fmt, ...)  printf("[ERROR]["MODULE_NAME"](%s|%d)"fmt,__func__,__LINE__, ##__VA_ARGS__)

 
int main(){

  int i = 1111;

  log_e("hello : i=%d\n", i);


  return 0;
}

root@lmw-virtual-machine:/home/lmw/桌面/C_Text#
root@lmw-virtual-machine:/home/lmw/桌面/C_Text# gcc my_log.c -o ab
root@lmw-virtual-machine:/home/lmw/桌面/C_Text#
root@lmw-virtual-machine:/home/lmw/桌面/C_Text# ./ab
[ERROR][MY_LIBS](main|14)hello : i=1111
root@lmw-virtual-machine:/home/lmw/桌面/C_Text#

 

 

 1.2

#include <iostream>
#include <stdio.h>
using namespace std;

#define Debug( fmt2,  arg12... )         \
    do{    printf("%s,  %s  %s\n", fmt2,  ##arg12);   \  // 这里有两个%s对应##arg12,所以就会打印出可变参数中的两个参数"what" 和"nice"
               printf("***************[%s-%s-%d]: "fmt2 , __FILE__, __FUNCTION__, __LINE__, ##arg12);  \
                             }while(0);

int main(){

  Debug("hi %s %s \n", "what", "nice"); // 针对这条打印进行分析

  return 0;
}

// 实测,第二条打印语句内的 "hi %s %s \n" 就是fmt2。  
//              而"what", "nice"是不定参数##arg12的值

 第二条打印语句分析: "hi %s %s \n"就是fmt2。 而"what", "nice"是不定参数##arg12的值。

需要注意的是: 如果只有1个%s格式符对应##arg12,那么只会打印出第一个"what",如果有两个格式符,那么则会打印出两个可变参数。

代码运行结果:

 

 

 

2. 编写一些功能函数的时候,我们也会用到可变参数

C++代码示例:

string combine_devtypes(int num, ...){

    string ret, tmp;
    va_list valist;
    char* str = NULL;
    int i;
 
    /* 为 num 个参数初始化 valist */
    va_start(valist, num);
 
    /* 访问所有赋给 valist 的参数 */
    for (i = 0; i < num; i++)
    {
       str = va_arg(valist, char*);
       tmp = str;
       ret += tmp;

       if(i < num-1){
         tmp = " ";
         ret += tmp;
       }
    }

    /* 清理为 valist 保留的内存 */
    va_end(valist);
 
    return ret;
}

本例子的函数功能是拼接字符串,并且在中间加上一个空字符。

调用方式: string obj = combine_devtypes(2, "hello", "boy") , 得到的是包含"hello boy"信息的这么一个字符串。

 

 

.

posted @ 2020-02-05 18:06  一匹夫  阅读(1763)  评论(0编辑  收藏  举报