具有以下标题的函数:
int max(int n, va_list vals)
在函数内部调用:
int max_first(int n, ...)
需要在主体开始时调用va_start(vals, n)
吗?我试过不用,它有效,但我不明白哪种方法是正确的。
int max(int n, va_list vals)
{
va_start(vals, n);
// etc
}
问题是
int max(int n, va_list vals)
在函数内部调用:
int max_first(int n, ...)
需要在主体开始时调用
va_start(vals, n)
吗?
不,它没有,而且它不能,正确的模式如下:
int max_first(int n, ...) {
va_list vals;
va_start(vals, n);
int rv = max(n, vals);
va_end(vals);
return rv;
}
然后
int max(int n, va_list vals) {
for (int i = 0; i < n; i ++) {
int val = va_arg(vals, int);
...
}
...
}
即,您只能在具有...
的函数中调用va_start
,并且您需要在...
之前传递参数,并且每次对va_start
的调用都必须始终后跟相同值的va_end
,如果您将其传递给函数,则必须在之后立即调用va_end
,而不在调用函数中使用它;如果要再次处理参数,则必须然后再次调用va_start
。
必须使用max_first
中的va_start
初始化va_list
。但您不能在max
中重做它,因为该函数没有必要的调用帧信息。
让我们从一些背景开始:根据文档,在任何va_list
:上调用va_arg
之前,您需要调用va_start
-
";在对va_arg"进行任何调用之前,应使用有效va_list对象ap的实例来调用va_start;。(来源(
-
"在调用va_arg之前,必须通过对va_start或va_copy的调用来初始化ap,而不需要对va_end"进行干预调用;。(来源(
我认为不调用va_start
是未定义的行为,但我找不到具体的调用来声明这一点。
在您的问题中,函数int max(int n, va_list vals)
不是";真的";varadic,因为它接受固定数量的参数:2
。它们是CCD_ 20和CCD_。
根据文献";变差函数的声明使用省略号作为最后一个参数,例如int printf(const char* format, ...);
〃;
因此,这取决于您如何实现它,但我建议记录int max(int n, va_list vals)
以接受已经用va_start
调用初始化的va_list
。其基本原理是;可变的";并不是真的";拥有";即CCD_ 26。它只是接受来自其他来源的输入。
实际的变差函数int max_first(int n, ...)
应该是创建va_list
并在将其传递到任何位置之前用对va_start
的调用启动它的函数。
不过,据我所知,没有办法检查va_list
是否已经调用了va_start
。并且不能保证它在传递给您的函数之前会被调用,所以我怀疑这必须通过文档和约定来强制执行。