3 回答
TA贡献1891条经验 获得超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分配内存,那么您就需要释放该内存。
这里的简短版本也是:因为语言标准是这样说的。
TA贡献1773条经验 获得超3个赞
va_start初始化变量参数列表。您总是将最后一个命名函数参数作为第二个参数传递。这是因为您需要提供有关堆栈中变量自变量开始的位置的信息,因为自变量被压入堆栈,并且编译器无法知道变量自变量列表的开始位置(没有区别)。
至于va_end,它用于释放在va_start调用期间分配给变量参数列表的资源。
- 3 回答
- 0 关注
- 355 浏览
添加回答
举报