c-调用带有va_list参数的函数一开始需要va_start()吗



具有以下标题的函数:

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。并且不能保证它在传递给您的函数之前会被调用,所以我怀疑这必须通过文档和约定来强制执行。

相关内容

  • 没有找到相关文章

最新更新