有没有一种标准的方法来确定va_args的数量?

Kir*_*rby 8 c++ variadic-functions

我正在使用va_args在C++中尝试变量参数.这个想法很有用,而且确实是我通过params功能在C#中使用了很多东西.让我感到沮丧的一件事是关于va_args的以下摘录,如上:

另请注意,va_arg不会确定检索到的参数是否是传递给函数的最后一个参数(或者即使它是超过该列表末尾的元素).

我发现很难相信没有办法以编程方式确定从该函数本身传递给函数的变量参数的数量.我想执行以下操作:

void fcn(int arg1 ...)
{
    va_list argList;
    va_start(argList, arg1);

    int numRemainingParams = //function that returns number of remaining parameters
    for (int i=0; i<numRemainingParams; ++i)
    {
        //do stuff with params
    }
    va_end(argList);
}
Run Code Online (Sandbox Code Playgroud)

重申一下,上面的文档表明va_arg不确定检索到的arg是否是列表中的最后一个.但我觉得这些信息必须以某种方式获取.

有没有一种标准的方法来实现这一目标?

ric*_*ici 10

我发现很难相信没有办法以编程方式确定从该函数本身传递给函数的变量参数的数量.

尽管如此,这是事实.C/C++不会在参数列表的末尾放置标记,因此被调用的函数实际上不知道它接收了多少个参数.如果需要标记参数的结尾,则必须通过在列表末尾添加某种标记来自行完成.

被调用的函数也不知道所提供的参数的类型或大小.这就是为什么printf和朋友强迫你指定要插入格式字符串的值的精确数据类型,以及为什么你可以通过调用带有错误格式字符串的printf来崩溃程序.

请注意,参数传递由ABI为特定平台指定,而不是由C++/C标准指定.但是,ABI必须允许C++/C标准可实现.例如,ABI可能希望在寄存器中传递参数以提高效率,但在这种情况下可能无法轻松实现va_args.所以参数也可能在堆栈上被遮蔽.但是,在几乎没有情况下,堆栈被标记为显示参数列表的结尾,因为C++/C标准不要求使这些信息可用,因此它将是不必要的开销.


Die*_*ühl 6

变量参数在C和C++中的工作方式相对简单:参数只是在栈上推送而且被调用者有责任在某种程度上弄清楚它们的参数.标准中没有提供确定参数数量的方法.结果,参数的数量由一些上下文信息确定,例如,格式字符串中引用的元素的数量.

个别编译器可能知道有多少元素,但没有标准接口来获取此值.

但是,你可以做的是使用可变参数模板:你可以确定传递给函数的参数的非常详细的信息.界面看起来不同,可能有必要将参数引入某种数据结构,但从好处来看,它也适用于您无法使用变量参数传递的类型.