变长列表参数

5

假设我有两个函数

void f1(int p1, int v1, ...);

AND

void f2(int v1, ...);

我想在f1函数中将可变参数列表中的所有参数传递给f2函数:

void f1(int p1, int v1, ...) {
   f2(/*pass all variadic parameters*/);
}

例如,当我调用 f1(1, 2, 3, 4, 5) 时,我想将2、3、4、5传递给 f2

将省略号传递给另一个可变参数函数 - Adam Rosenfield
3个回答

4

尽管您已经接受了一个正确的答案。

如果您无法访问f2,则可以使用可变宏的替代方法。这是自C99以来可用的一种方法:

#define F1(P1, V1, ...)           \
do {                              \
   /* do something with P1, V1 */ \
   f2(__VA_ARGS__);               \
} while(0)

这里的 do-while 只是一个技巧,用于封装您的语句,以便调用该宏可以出现在任何普通语句可以出现的地方,并且所有的 \ 帮助将宏写成多行。

这样的宏通常用于增强 printf 以打印带有前缀的日志消息,例如:

#define dprintf(...)                               \
do {                                               \
   fprintf(stderr, "%lX: ", (long unsigned)mynum); \
   fprintf(stderr, __VA_ARGS__);                   \
} while(0)

3

直接实现不可能,但你可以使用 va_list 类型将参数打包,然后传递给一个接收该参数的函数。基本上,将 f2() 拆分为:

void f2v(int v1, va_list args) {
    // ...
    // use va_arg() repeatedly to get the various arguments here
}

void f2(int v1, ...) {
    va_list args;
    va_start(args, v1);
    f2v(v1, args);
    va_end(args);
}

然后重新设计f1(),使用f2v()替代f2()

void f1(int p1, int v1, ...) {
    // do whatever else you need to do before the call to f2

    va_list args;
    va_start(args, v1);
    f2v(v1, args);
    va_end(args);

    // do whatever else you need to do after the call to f2
}

理论上,printf()vprintf()的工作原理是这样的--printf()内部可以调用vprintf(),因此不需要两个功能实现完全相同的函数。

(别忘了,你需要#include <stdarg.h>来访问va_listva_start()等函数。)


谢谢。这实际上是我担心的情况。不幸的是,我无法访问f2并且无法重写它。 - Ivan
那么在C语言中,您无法以可移植的方式完成它。如果您告诉我们f2()实际上是什么,我们可能能够提供替代方案。 - Jonathan Grynspan
这是一个来自外部库的函数(我无法访问源代码)。而且我也没有其他选择。不管怎样,还是谢谢您。 - Ivan
只要您不必处理参数(例如,不必剥离第一个参数),就可以使用作为跳板的汇编代码来完成此操作。这将既不直截了当也不太坚固。 - bbum
因此我说“你不能以可移植的方式做到这一点”——当涉及汇编语言时,所有的赌注都是无效的。 - Jonathan Grynspan

0
一般来说,你不能这样做。不过,可以参考这个问题

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接