C语言中可变参数的宏 __VA_ARGS__

C语言之#和##和__VA_ARGS__和##__VA_ARGS__ 1、问题 看到代码宏里面很多##__VA_ARGS__不知道什么意思 2、直接写测试代码 #include <stdio.h> #define my_printf(x) printf(#x" is %d\n", x) #define my_printf1(x) printf("value is %d\n", x##x) #define my_printf2(...... 阅读详情

C语言中可变参数的宏 __VA_ARGS__

 

1.#

假如希望在字符串中包含宏参数,ANSI C允许这样作,在类函数宏的替换部分,

#符号用作一个预处理运算符,它可以把语言符号转化成字符串。

 

例如,如果x是一个宏参量,那么#x可以把参数名转化成相应的字符串。该过程称为字符串化(stringizing).

#incldue <stdio.h>

#define PSQR(x) printf("the square of" #x "is %d.\n",(x)*(x))

 

int main(void)

{

   int y =4;

   PSQR(y);

   PSQR(2+4);

   return 0;

}

输出结果:

the square of y is 16.

the square of 2+4 is 36.

第一次调用宏时使用"y”代替#x;第二次调用时用"2+4"代#x。

 

2.##

##运算符可以使用类函数宏的替换部分。另外,##还可以用于类对象宏的替换部分。

这个运算符把两个语言符号组合成单个语言符号。

 

例如:

#define XNAME(n) x##n

这样宏调用:

XNAME(4)

展开后:

x4

 

 

程序:

#include <stdio.h>

#define XNAME(n) x##n

#define PXN(n) printf("x"#n" = %d\n",x##n)

 

int main(void)

{

   int XNAME(1)=12;//int x1=12;

   PXN(1);//printf("x1 = %d\n", x1);

   return 0;

}

 

 

3. __VA_ARGS__

__VA_ARGS__可以用于替换参数列表。程序如下:

 

#include <stdio.h>  

#include <fstream>

#include <iostream>

#include <time.h>

#include <string>

using namespace std;

void SaveLog(char* cFileName, char* cFormat, ... )

{

 char cBuffer[2048];

 memset( cBuffer, 0, 2048 );

 

 va_list argptr;

 va_start( argptr, cFormat );

 vsprintf_s( cBuffer, 2048, cFormat, argptr );

 va_end( argptr );

 

 time_t t = time(NULL);

 char* cDate = ctime(&t);

 

 ofstream file( cFileName, ios::app );

 file.write(cDate, strlen(cDate)-1);

 file << ends;

 file << cBuffer << endl;

 file.close();

 

}

 

#define ENABLE_SAVE_LOG

#ifdef ENABLE_SAVE_LOG

#define SAVE_LOG(x, ...) SaveLog("test.log", "%s: "##x, __FUNCTION__, ##__VA_ARGS__)

 

#else

#define SAVE_LOG(x, ...)

#endif

这里的##起到把前面多余的","去掉作用,当可变参数的个数为0时,实际上变成了SAVE_LOG(x).

 

1、 __VA_ARGS__ 是一个可变参数的宏,很少人知道这个宏,这个可变参数的宏是新的C99规范中新增的,

    目前似乎只有gcc支持(VC6.0的编译器不支持)。宏前面加上##的作用在于,当可变参数的个数为0时,

    这里的##起到把前面多余的","去掉的作用,否则会编译出错, 你可以试试。

 

2、 __FILE__ 宏在预编译时会替换成当前的源文件名

 

3、__LINE__宏在预编译时会替换成当前的行号

 

4、__FUNCTION__宏在预编译时会替换成当前的函数名称

 

 

 

 

__VA_ARGS__用法 调试信息的输出方法有很多种,  例如直接用printf,  或者出错时使用perror, fprintf等将信息直接打印到终端上, 在Qt上面一般使用qDebug,而守护进程则一般是使用syslog将调试信息输出到日志文件中等等 立即下载

相关推荐

关于石墨烯费米能级和偏置电压之间的关系问题

石墨烯费米能级与电压的关系问题

qq_37946542的博客 3514

怎么让VC6.0支持可变参数宏定义?

用不着重载()这样就行:#include &lt;stdarg.h&gt; //包含va_list#include &lt;stdio.h&gt; //包含vsprintf()#include &lt;string.h&gt;#define MyPrtLog CPrtLogFunc(__FILE__,__LINE__).outclass CPrtLogFunc { public:     char...

zerokkqq的专栏 1760

OpenAI Codex 桌面端国内使用全坑解決指南(2026 Windows 实测)

本地文件报错:SQLite 初始化失败、启动闪退、卡加载页 → 本地缓存/数据库损坏,和网络无关网络地区报错→ 网络IP/地区被拦截,和本地软件文件无关Codex 桌面端的大部分报错,都不是软件故障,而是海外软件适配国内网络、国内模型协议不兼容导致的适配问题。不用盲目重装、换网络、改系统设置,只要区分「本地文件问题」和「网络地区问题」,搭配国内大模型 API 替代方案,就能完美解决所有痛点。(注:部分内容可能由 AI 生成)

ups_hxc的博客 1066

C语言可变参数的实现

x86函数调用惯例 在开始说明可变参数的实现之前,我们要说说x86函数调用的一些惯例。函数参数传递是从右向左的入栈顺序,在x86体系中,用户栈是从用户地址空间的顶端开始向下拓展的。 va_list 可变参数由类型 va_list,一组宏va_start,va_arg,va_end实现。宏的实现根据编译器而有所不同。 下面以VC6.0为例说明va_list的实现。 假设一个函数调用fo...

dennis的专栏 2568

EL6751实战指南:从协议解析到工业现场部署

本文详细介绍了EL6751网关在工业通信协议转换中的应用,从CANopen协议解析到EtherCAT系统部署的实战指南。通过协议栈位置、数据封装方式和通信模型差异的深入分析,帮助工程师高效实现EtherCAT主站与CANopen从站设备间的无缝对接,提升工业现场通信效率。

weixin_30338481的博客 546

Linux系统搭建OpenClaw(原Clawdbot)全流程指南 最新版

工具定位:开源个人 AI 助手,支持文件读取、命令执行、多渠道交互(Telegram / 本地终端等);系统要求:主流 Linux 发行版(Ubuntu/Debian/CentOS 等),Node.js ≥22(核心依赖);安全提示:OpenClaw 为测试版,具备高权限操作能力,建议使用非主力机,配置权限白名单,避免接触敏感数据。

AI时代老码农的第二春 6559

C语言怎么实现可变参数?

C语言怎么实现可变参数? 摘要 原理 例子 自己动手实现可变参数 C语言使用可变参数,需要借助宏。这些宏定义在stdarg.h文件。stdarg.h声明了一个类型va_list和三个宏va_start,va_arg,va_end。 #include<stdarg.h> va_list v_arg; //定义一个类型 va_start(v_arg,len); //参数列表初始化 va_arg(v_arg, int); //获取列表中第一个参数,第二个形参是参数类型 va_arg(v_ar

Dsduming的博客 893

云卓遥控器+DIY高清摄像机的方案(完美接入原系统)

发云卓H16 1080P数图控三合一10公里 其中它月

fgh00000的博客 1万+

Windows下C/C++可变参数宏实现技巧

Windows下C/C++可变参数宏实现技巧在开发过程中,有很多阶段,每个阶段可能会注重不同的重点,我们可能会在不同阶段让程序输出或者打印不同的信息以反应运行的情况,所以我们必须分阶段的使得程序输出我们在每个阶段所要关心的信息,甚至在最后让程序不再输出信息。这就要用到了宏定义!      我们知道,在linux下很方便的就能实现可变参数宏的定义,比如:#define myprint

DoYou?'s csdn 1万+

Synopsys工具链实战:如何用VCS、DC、ICC和Calibre跑通你的第一个数字IC设计项目?

本文详细介绍了如何使用Synopsys工具链(VCS、Design Compiler、ICC和Calibre)完成数字IC设计项目,从RTL代码到GDSII版图的全流程。涵盖环境配置、RTL设计验证、逻辑综合、物理实现及签核验证等关键步骤,帮助工程师掌握高效的数字IC设计流程。

weixin_42525005的博客 196

ubuntu安装eigen3.3.7

查看已安装版本: gedit /usr/include/eigen3/Eigen/src/Core/util/Macros.h 或 gedit /usr/local/include/eigen3/Eigen/src/Core/util/Macros.h 卸载先前版本: sudo updatedb locate eigen3 得到eigen库的位置 卸载: sudo rm -rf /usr/include/eigen3 /usr/lib/cmake/eigen3 ...

reason的博客 1万+

c语言 可变参数的宏,可变参数的宏__ VA_ARGS__的用法

回顾在【ANSIC几种特殊的标准定义】中我们讲述了比较常用的几项:__FILE__:正在编译文件的路径及文件名__LINE__:正在编译文件的行号__DATE__:编译时刻的日期字符串 如“Jun 17 2017”__TIME__:编译时刻的时间字符串 如”1000“代码:char BuildFile[] = __FILE__;int BuildLine = __LINE__;char Build...

weixin_39756895的博客 335

STM32实战开发(133):基于STM32的智能GPS定位跟踪系统开发

本文详细介绍了如何基于STM32开发一个智能GPS定位跟踪系统。系统使用NEO-6M GPS模块获取实时定位数据,并通过SIM800L GPRS模块将定位信息上传到远程服务器。通过OLED屏幕实时显示位置数据,使用SD卡存储历史轨迹,并提供蜂鸣器报警功能。项目实现了GPS定位数据的获取、解析、存储和传输,为智能定位系统提供了完整的解决方案。

2201_76125393的博客 1643

c 语言 宏 可变 参数,C / C++ 可变参数的宏,__VA_ARGS__,...

C++ Builder 参考手册 ➙ C / C++ 可变参数的宏,__VA_ARGS__,...宏的可变参数的写法例子一. 宏的可变参数的写法1. 单独的 ... 和 __VA_ARGS__标准 C / C++ 语言宏定义的参数允许用三个小数点 ... 表示这里是可变参数,在宏替换的时候,用 __VA_ARGS__ 表示 ... 位置的所有的参数。例如:#define test1(...) pr...

weixin_35048609的博客 642

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

C语言练级->##__VA_ARGS__(可变参数)的用法

这个##将逗号和__VA_ARGS__拼接起来,结果__VA_ARGS__此时为空,和逗号拼接后相当于逗号被拿走了,如果平时有可变参数传入时,这时就算拼接了,那也是正常显示逗号,所以没问题。首先##和__VA_ARGS__其实是没什么关联的,##有单独的语法说明,__VA_ARGS__也只是一个宏参数。由上可知:__VA_ARGS__和...的分工是明确的,一个是在定义使用,一个是在宏体内使用。通常__VA_ARGS__用于宏定义,其中关于日志宏需要用的,printf 等支持可变参数的函数的宏封装。

a1275174052的博客 1187

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

不清不楚之C语言中##__VA_ARGS__与__VA_ARGS__

正文大家好,我是bug菌~最近在开发过程中又玩起了C语言的可变参数,在资源受限的MCU平台上,一般不太建议使用可变参数或者相应标准库函数如printf等,以免编译进去后导致程序代码段瞬间变大很多,当然有些简化版本的lib,不过也相当废资源,不过现在MCU的性能越来越卷,大部分项目都是资源过剩。不过话说回来,C语言的可变参数用起来还挺顺手,像嵌入式经常打印的日志,为了更好的可移植性通常会进行封装,今...

最后一个bug的博客 1513

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

##__VA_ARGS__与##args的用法

本文主要涉及##__VA_ARGS__与##args的用法

lihuan680680的博客 4672

关于__VA_ARGS__宏的一个小探索

关于__VA_ARGS__的用法和一些关于C语言可变参数的联想。

qq_42935201的博客 506

C语言 可变参数列表及相关宏

C语言可变参数相关的宏介绍

qq_52508038的博客 839

c语言宏展开中的__VA_ARGS, ##__VA_ARGS 是什么意思?.

文章摘要: 本文通过示例代码解析了C语言宏定义中__VA_ARGS__和##__VA_ARGS__的用法及区别。__VA_ARGS__代表可变参数列表,用于传递不定数量的参数;而##__VA_ARGS__在参数为空时会自动去除前置逗号,避免语法错误。文中通过三个my_printf宏的对比演示了两者的实际差异,并解释了直接使用printf与封装宏的区别在于代码风格和可读性。最后指出宏虽能简化代码但可能降低可理解性,需谨慎使用。

hjjdebug的专栏 857

C语言 ##__VA_ARGS__ - C语言零基础入门教程

目录 一.##__VA_ARGS__原理 二.##__VA_ARGS__使用 三.猜你喜欢 零基础 C/C++ 学习路线推荐 : C/C++ 学习目录 >> C 语言基础入门 一.##__VA_ARGS__原理 C 语言中 __VA_ARGS__ 是一个可变参数的宏,是新的 C99 规范中新增的,目前似乎只有 gcc 支持( VC 从 VC2005 开始支持)。 [__VA_ARGS__](https://www.codersrc.com/archives/9450.html) 在前面的

猿说编程 638

【c语法】##__VA_ARGS__与__VA_ARGS__

_VA_ARGS__是C语言设定的一个预定义宏,用于处理可变参数的参数列表。通常用在宏定义中,以便宏可以接收不定数量的参数,并将他们作为整体处理。__VA_ARGS__表示所有在宏调用中传递的额外参数。当想要在自定义的调试信息加上时间、行数等信息时,应该怎么做呢?在调试过程中,我们经常会自定义打印,比如日志信息的输出,这时就会用。,下列的代码均在C99及C99以上标准的环境下运行。,为了定义可以处理不同参数个数的宏,如上的代码就是对日志定义的一个宏。:可变参数为空时,报错。

2301_79181030的博客 2175

C/C++:可变参数宏以及##和#符的使用

在C语言的宏中,#的功能就是将字符串中的宏参数进行字符串转化操作,简单说就是在将字符串中的宏变量原样输出并在其左右各加上一个双引号。

WHEgqing的专栏 635

c++ 之处理可变参数

使用va_list 或者springf对可变参数进行格式化处理 #include<stdarg.h> #include<stdio.h> void trace_log(const char* format, ...); void trace_log1(const char* format, ...); int main() { trace_log("%s,%d\n", ...

enjoy.day 521

#define中使用的参数#、##、__VA_ARGS__和##__VA_ARGS__

#在预编译时期将宏参数转换为字符串 #define PRINT_MACRO_HELPER(x) #x #define PRINT_MACRO(x) PRINT_MACRO_HELPER(x) #define PRINT_ANOTHER_MACRO(x) #x"="PRINT_MACRO_HELPER(x) char *str=PRINT_MACRO_HELPER(1235982536); char *str2=PRINT_MACRO(i); char *str3=PRINT_ANOTHER_MACRO(i)

qq_22267967的博客 1497

#、##、__VA_ARGS__和##__VA_ARGS__的作用

一、#用来把参数转换成字符串 例子一: #define P(A) printf("%s:%d\n",#A,A); int main(int argc, char **argv) { int a = 1, b = 2; P(a); P(b); P(a+b); system("pause"); } 输出为: 例子二: #define SQUARE(x) printf("The square of...

木牛的博客 218
上一篇: spinlock与linux内核调度的关系
下一篇: 创建简单的静态库和动态库
废言Pro
博客等级 码龄16年 1092粉丝 142原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值