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

摘要:
//虽然“what”和“nice”是不定参数##arg12的值,但第二个print语句分析:“hi%s%s”是fmt2。注意:如果只有一个%s格式字符对应于##arg2,则只会打印第一个“what”。如果有两个格式字符,将打印两个变量参数。代码运行结果:2.在编写一些函数函数时,我们还将使用变量参数C++代码示例:stringcombine_Devtypes{stringret,tmp;va_listvalist;char*str=NULL;inti;/*初始化num参数的valist*/va_start;/*访问分配给valist的所有参数*/for{str=va_arg;tmp=str;ret+=tmp;if{tmp=“”;ret+=tmp;}/*清除为有效*/va_end保留的内存;returnret;}此示例的功能是连接字符串并在中间添加一个空字符。

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

1.1

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

 ##__VA_ARGS__      之详细解析

例如:

case A.

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

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

case B.

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

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

正确打印

my_print2("iiiiiii ")       

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

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
", 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
", fmt2,  ##arg12);     // 这里有两个%s对应##arg12,所以就会打印出可变参数中的两个参数"what" 和"nice"
               printf("***************[%s-%s-%d]: "fmt2 , __FILE__, __FUNCTION__, __LINE__, ##arg12);  
                             }while(0);

int main(){

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

  return 0;
}

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

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

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

代码运行结果:

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

 

 

 

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"信息的这么一个字符串。

 

 

.

免责声明:内容来源于网络,仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇asp.net CommandArgument用法文件权限及chmod使用方法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

VS2019配置MKL教程(Windows)

下载链接:https://software.intel.com/en-us/mkl 文件下载 官网注册后,选择MKL下载下来,安装到指定目录就行,不在多说。 配置文件 首先创建一个Windows桌面项目,再添加一个CPP源文件。 打开项目属性页--配置属性,会多出Intel Performance...这一项,看下图配置 在打开VC++目录,进行配置...

STM32CubeIDE使用ITM调试

以前用Keil MDK总喜欢用一个串口,使用printf函数往串口助手上打印一些提示信息。发现使用ITM比使用串口调试好使一点,但是前提是,必须要用调试器,J-Link或者ST-Link,ST-Link还必须要有SWO这根线,也就是一般开发板上带的4线的SWD接口是不行的。下面记录一下我的配置过程。 打开IDE新建STM32工程,file-->new...

Linux中 diff与patch的深入分析(转)

本文转自http://linux.chinaitlab.com/c/805820.html 1) diff的传统格式输出.   ############################################   cat before.txt   输出:   This is a line to be deleted   This is a line...

c提取文件路径、文件名和后缀名

/* MAKEPATH.C */ #include <stdlib.h> #include <stdio.h> void main( void ) { char path_buffer[_MAX_PATH]; char drive[_MAX_DRIVE]; char dir[...

Linux系统编程——水平触发和边沿触发

事件模型 Edge Triggered (ET) 边缘触发只有数据到来,才触发,不管缓存区中是否还有数据。 Level Triggered (LT) 水平触发只要有数据都会触发。 首先介绍一下LT工作模式: LT(level triggered)是缺省的工作方式,并且同时支持block和no-block socket.在这种做法中,内核告诉你一个文件描述符...

openssl 学习之从证书中提取RSA公钥N 和 E

原文链接:http://blog.csdn.net/kkxgx/article/details/19850509 通常数字证书包含很多信息,其中N和E值即我们称为的公钥。如何从PEM 或者DER格式的证书中提出证书呢?下面给出代码实现从PEM和DER编码的证书中提出N、E。 [cpp]view plaincopy #include<open...