C语言怎样写参数个数可变的宏?

一、问题

在C语⾔中存在参数个数可变的函数,那么是否也存在参数个数可变的宏呢?如果存在,怎样写参数个数可变的宏呢?

二、解答

在C语⾔中存在参数个数可变的宏,⾸先⼤致了解⼀下什么是参数个数可变的函数, printf( )和 scanf( )函数是使⽤最频繁的参数个数可变的函数。

下⾯这个例⼦是参数个数可变的函数的应⽤,相应代码如下。

cpp 复制代码
#include <stdio.h>
#include <stdarg.h>
int func(int first, int second, ...)
{
    int s = 0, t = first;
    va_list v1;
    va_start(v1, first);
    while (t != -1)
    {
        s += t;
        t = va_arg(v1, int);
    }
    va_end(v1);
    return s;
}
int main(int argc, char *argv[])
{
    printf("个数不定的参数的和为s=%d\n", func(50, 10, 12, 20, -1));
    printf("个数不定的参数的和为s=%d\n", func(50, 10, 12, 20, 8, -1));
    return 0;
}

此例实现了⼀个参数个数不确定的求和的函数 func( ),在 func( )函数中输⼊任意个数的参数,输出这⼏个参数的和。例如,输⼊参数 50、10、 12、 20、-1,可以得到这⼏个参数的和为92。其中,-1是参数结束标志。当输⼊ 50、10、12、20、8、-1时,函数得到的计算结果为100。

此程序的运⾏结果如下所示。

cpp 复制代码
个数不定的参数的和为s=92
个数不定的参数的和为s=100

上述例⼦中,函数中⼀开始定义了⼀个 v_list 型变量 v,该变量⽤来访问可变参数, 实际上就是指针,接着使⽤ va_start 使v1指向第⼀个参数,然后再使⽤ va_arg 来遍历每⼀ 个参数,va_arg 返回参数列表中的当前参数并使 v1指向参数列表中的下⼀个参数。最后通 过 va_end 把v1指针清为 NULL。在这⾥,va_ start,va_arg,va_end 其实都是宏。

参数个数可变的宏与参数个数可变的函数⼤体是相似的,都是参数个数不确定。了解了如何编写⼀个参数个数可变的函数,那么如何编写⼀个参数个数可变的宏也就可以理解了。

一种流⾏的技巧是⽤⼀个单独的⽤括号括起来的"参数"定义和调⽤宏,参数在宏扩展的时候成为类似 printf( )那样的函数的整个参数列表。例如:

cpp 复制代码
#define DEBUG(args) (printtf("DEBUG:"), printf args)
if (n != 0)
    DEBUG(("n is %d\n", n));

注意:

调⽤者必须记住使⽤⼀对额外的括号括起,如"DEBUG(("n is %d\n",n));"。

GCC 有⼀个扩展可以让函数式的宏接受可变个数的参数。但这并不是标准,另⼀种可能的解决⽅案是根据参数个数使⽤多个宏,如 DEBUG1、 DEBUG2 等,或者⽤逗号表示成如下形式。

cpp 复制代码
#define DEBUG(args) (printf("DEBUG:"),printf args)
#define_,
DEBUG("i=%d"_i);

C99 引⼊了对参数个数可变的函数式宏的正式⽀持。在宏"原型" 的末尾加上符号"..."宏定义中的伪宏_VA_ARGS_就会在调⽤时替换成可变参数。例如:

cpp 复制代码
#define dgbmsg(fmt...)\
printf(fmt,_VA_ARGS_)

这⾥"..."表示可变参数。

三、总结

起初,可变参数还只是应⽤在真正的函数中,不能应⽤在宏中。直到 C99 编译器标准的出现,改变了这种局⾯,它允许定义参数可变的宏。虽然 GCC 也可以定义参数个数可变的宏,但是它并不是标准的。

相关推荐
wenxin-3 分钟前
NS3网络模拟器中如何利用Gnuplot工具像MATLAB一样绘制各类图形?
开发语言·matlab·画图·ns3·lr-wpan
数据小爬虫@2 小时前
深入解析:使用 Python 爬虫获取苏宁商品详情
开发语言·爬虫·python
健胃消食片片片片2 小时前
Python爬虫技术:高效数据收集与深度挖掘
开发语言·爬虫·python
王老师青少年编程3 小时前
gesp(C++五级)(14)洛谷:B4071:[GESP202412 五级] 武器强化
开发语言·c++·算法·gesp·csp·信奥赛
DogDaoDao3 小时前
leetcode 面试经典 150 题:有效的括号
c++·算法·leetcode·面试··stack·有效的括号
Coovally AI模型快速验证4 小时前
MMYOLO:打破单一模式限制,多模态目标检测的革命性突破!
人工智能·算法·yolo·目标检测·机器学习·计算机视觉·目标跟踪
一只小bit4 小时前
C++之初识模版
开发语言·c++
王磊鑫5 小时前
C语言小项目——通讯录
c语言·开发语言
钢铁男儿5 小时前
C# 委托和事件(事件)
开发语言·c#
可为测控5 小时前
图像处理基础(4):高斯滤波器详解
人工智能·算法·计算机视觉