为什么不可能将所有可变参数作为C中的可变参数转发?

为什么不可能将所有可变参数作为C中的可变参数转发?,c,variadic-functions,C,Variadic Functions,man stdarg(3)展示了如何编程可变函数的示例。但是最外层的可变函数调用的函数不是可变的 有没有一种方法可以在这样的变量函数中调用变量,并且所有参数都按原样传递?如果是的话,有人能告诉我如何做的细节吗 void foo(char *fmt, ...) { printf(fmt, ...) // not sure how to call a variadic function here ... is just ... from foo } 编辑:中没有一个答案清楚地回答了我的问题 如果答

man stdarg(3)展示了如何编程可变函数的示例。但是最外层的可变函数调用的函数不是可变的

有没有一种方法可以在这样的变量函数中调用变量,并且所有参数都按原样传递?如果是的话,有人能告诉我如何做的细节吗

void foo(char *fmt, ...) {
printf(fmt, ...) // not sure how to call a variadic function here ... is just ... from foo
}
编辑:中没有一个答案清楚地回答了我的问题

如果答案是“不可能”,请明确回答为“不可能”。而不是提供任何无关的东西。我不需要任何替代方案


此外,如果“不可能”,有人能证明为什么不可能。该链接中的任何答案都无法回答此问题。因此,这篇文章应该对我的问题保持开放的态度。

事实上,在gcc中这是可能的,它有一个鲜为人知的内置功能,允许您“构造”函数调用

例如,哪一个收到了你想要的,它不是最受欢迎的。下面是该示例代码的重新发布,用于保存单击:

int my_printf(const char *fmt, ...) {
    void *args = __builtin_apply_args();
    printf("Hello there! Format string is %s\n", fmt);
    void *ret = __builtin_apply((void (*)())printf, args, 1000);
    __builtin_return(ret);
}

int main(void) {
    my_printf("%d %f %s\n", -37, 3.1415, "spam");
    return 0;
}
这项功能还没有在clang中重新实现,尽管你可以在档案中看到它的有趣之处

所以回到你最初的可能性问题,我想我们必须澄清在这种情况下什么是“可能的”。除了
va_列表
之外,无法引用变量参数列表。像gcc这样的编译器可以使用自己的扩展来处理这个问题(比如
\uuuuu builtin\uapply
),但它们总是不可移植和非标准的

你可能想问的下一个问题是“为什么”,我真的只能猜测答案,但我相信这可能是因为这样做需要对ABI和调用约定附加一些约束和要求,C和C++规范尽量避免。 一般来说,一个被调用的函数不知道在它进入堆栈之前有多少东西被推到了堆栈上,我也不知道有哪种ABI要求在所有情况下都提供这些信息。如果

foo()

只有编写函数的人才知道如何迭代调用堆栈,为此选择的语法是使用
va_list
对象


当然,不难看出如何创建一个允许传递参数计数和长度的ABI,但如果世界上所有你实际上要调用的库都不符合你的ABI,这是一个学术练习。

一般来说,您必须调用一个接受
va_list
参数的函数版本。没有通用方法。编写变量函数时,如果希望有人能够从其变量函数调用变量,还必须提供一个接受
va_list
参数的版本。答案是否为“不可能”?在所有参数都按原样传递的情况下,无法从变量函数调用变量函数?为什么?因为从来没有人想要或实现这样的功能,他们也从来没有费心将其标准化。关键是,使用
va_列表
是处理变量参数的标准化、可接受的方式。如果您的设计依赖于一个变量函数调用另一个变量函数,则需要更改您的设计。事实上,值得注意的是,
\u builtin\u apply
要求您为其指定要复制的堆栈字节数的上限,因此它不能完全通用。此外,它无条件地复制字节数,这使得参数数通常很小但可能很大时效率非常低。