栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C语言##

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C语言##

C语言可变参数函数详解
  • 0 前言
  • 1 __VA_ARGS__的用法
  • 2 ##__VA_ARGS__的用法
  • 总结

0 前言

在调试过程中,有时会用到自定义的打印,这是就会用到##__VA_ARGS__,接下来详细讲解。

1 __VA_ARGS__的用法

自定义打印时,用到可变参数,用...即可表示可变参数,如下:

#include 

#define LOG1(...)               printf(__VA_ARGS__)//...表示可变参数,__VA_ARGS__就是将...的值复制到这里
int main(int argc, char** argv)
{
    char *str = "test __VA_ARGS__";
    int num = 10086;
    LOG1("this is test __VA_ARGS__rn");
    LOG1("this is test __VA_ARGS__:%s, %drn", str, num);

    return 0;
}

打印结果如下:

this is test __VA_ARGS__
this is test __VA_ARGS__:test __VA_ARGS__, 10086
2 ##__VA_ARGS__的用法

##__VA_ARGS__前面加上##的作用是:当可变参数的个数为0时,这里的##可以把把前面多余的","去掉,否则会编译出错。
当想要在自定义的调试信息加上时间、行数等信息时,应该怎么做呢?先把正确的用法写在前面:

#include 

#define LOG3(fmt, ...)          printf("<%s:%s>:"fmt"rn", __FILE__, __FUNCTION__, ##__VA_ARGS__)
int main(int argc, char** argv)
{
    char *str = "test __VA_ARGS__";
    int num = 10086;
    
    LOG3("this is test __VA_ARGS__");
    LOG3("this is test __VA_ARGS__:%s, %d", str, num);
    LOG3();

    return 0;
}

打印如下:

:this is test __VA_ARGS__
:this is test __VA_ARGS__:test __VA_ARGS__, 10086
:

然后做比较:如果用__VA_ARGS__,当使用时,参数为空,编译报错。如下:

#include 

#define LOG2(fmt, ...)          printf("<%s:%s>:"fmt"rn", __FILE__, __FUNCTION__, __VA_ARGS__)
int main(int argc, char** argv)
{
    LOG2();//不传参数,编译报错
    LOG2("this is test __VA_ARGS__");//编译报错
    LOG2("this is test __VA_ARGS__:%s, %d", str, num);//正常编译
    return 0;
}

编译后报错:

main.c: In function ‘main’:
main.c:3:96: error: expected expression before ‘)’ token
   3  | #define LOG2(fmt, ...)          printf("<%s:%s>:"fmt"rn", __FILE__, __FUNCTION__, __VA_ARGS__)
      |                                                                                                ^
main.c:6:5: note: in expansion of macro ‘LOG2’
   6  |     LOG2();//不传参数,编译报错
      |     ^~~~
main.c:3:96: error: expected expression before ‘)’ token
   3  | #define LOG2(fmt, ...)          printf("<%s:%s>:"fmt"rn", __FILE__, __FUNCTION__, __VA_ARGS__)
      |                                                                                                ^
main.c:7:5: note: in expansion of macro ‘LOG2’
   7  |     LOG2("this is test __VA_ARGS__");
      |     ^~~~

分析:

  • 第6行没有传参数,宏定义LOG2(fmt,...)展开后,__VA_ARGS__是空的,这时printf后面剩余一个,,必然编译失败;
  • 第7行虽然传入了字符串,但是该字符串赋值给了LOG2(fmt,...)的第一个参数fmt,宏展开后,printf后面也剩余一个,,所以编译报错。
总结

##__VA_ARGS__中##的作用就是去掉前面多余的,,在使用自定义打印的时候,推荐使用第2小节的方式。

欢迎大家评论区留言交流!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/983304.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号