在C中使用varargs的示例

在这里,我找到了一个示例,说明如何在C中使用varargs。


#include <stdarg.h>


double average(int count, ...)

{

    va_list ap;

    int j;

    double tot = 0;

    va_start(ap, count); //Requires the last fixed parameter (to get the address)

    for(j=0; j<count; j++)

        tot+=va_arg(ap, double); //Requires the type to cast to. Increments ap to the next argument.

    va_end(ap);

    return tot/count;

}

我只能在某种程度上理解此示例。


我不清楚我们为什么使用va_start(ap, count);。据我了解,通过这种方式,我们将迭代器设置为其第一个元素。但是,为什么默认情况下不将其设置为开头?


我不清楚为什么我们需要给出count一个论据。C不能自动确定参数的数量吗?


我不清楚我们为什么使用va_end(ap)。它会发生什么变化?是否将迭代器设置为列表的末尾?但是不是通过循环将其设置为列表的末尾吗?而且,为什么我们需要它?我们不再使用ap;我们为什么要更改它?


qq_遁去的一_1
浏览 356回答 3
3回答

万千封印

但是,为什么默认情况下不将其设置为开头?也许是由于历史原因导致的,当时编译器还不够聪明。可能是因为您可能拥有一个varargs函数原型,而该原型实际上并不在乎varargs,而在该特定系统上设置varargs恰好很昂贵。可能是因为va_copy您要执行更复杂的操作,或者您想多次重新启动参数并多次调用va_start。简短的版本是:因为语言标准是这样说的。第二,对我来说不清楚,为什么我们需要计数。C ++不能自动确定参数的数量吗?那不是全部count。它是函数的最后一个命名参数。va_start需要它来找出可变参数在哪里。这很可能是由于旧编译器的历史原因所致。我不明白为什么今天不能以不同的方式实现它。问题的第二部分:不,编译器不知道向该函数发送了多少个参数。它甚至可能不在同一编译单元或同一程序中,并且编译器也不知道该函数将如何被调用。想象一个具有varargs函数的库,例如printf。当您编译libc时,编译器不知道何时以及如何调用程序printf。在大多数ABI上(ABI是如何调用函数,如何传递参数的约定,等等),无法找出函数调用获得了多少个参数。将这些信息包含在函数调用中非常浪费,而且几乎不需要。因此,您需要一种方法来告诉varargs函数有多少个参数。存取中va_arg 未定义的行为超出了实际传递的参数数量。然后我不清楚我们为什么要使用va_end(ap)。它会发生什么变化?在大多数架构va_end上,没有任何相关的事情。但是有些架构具有传递自变量语义的复杂参数,va_start甚至可能潜在地va_end分配内存,那么您就需要释放该内存。这里的简短版本也是:因为语言标准是这样说的。

慕容3067478

va_start初始化变量参数列表。您总是将最后一个命名函数参数作为第二个参数传递。这是因为您需要提供有关堆栈中变量自变量开始的位置的信息,因为自变量被压入堆栈,并且编译器无法知道变量自变量列表的开始位置(没有区别)。至于va_end,它用于释放在va_start调用期间分配给变量参数列表的资源。
打开App,查看更多内容
随时随地看视频慕课网APP