为什么可变参数函数需要至少两个参数?
我正在努力填补我知识中的漏洞。为什么可变参数函数需要至少两个参数?主要来自 C 的 main
函数,其中 argc
作为参数计数,然后 argv
作为字符数组的数组? Objective-C 的 Cocoa 也有 NSString
方法,需要将 format 作为第一个参数,然后是参数数组 ([NSString stringWithFormat:@"%@", foo]
)。为什么不可能创建只接受参数列表的可变参数函数?
I'm trying to plug a hole in my knowledge. Why variadic functions require at least two arguments? Mostly from C's main
function having argc
as argument count and then argv
as array of arrays of chars? Also Objective-C's Cocoa has NSString
methods that require format as first argument and afterwards an array of arguments ([NSString stringWithFormat:@"%@", foo]
). Why is it impossible to create a variadic function accepting only a list of arguments?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
argc/argv 的东西并不是真正的可变参数。
可变参数函数(例如
printf()
)使用放在堆栈上的参数,并且不需要至少 2 个参数,但需要 1 个。您有
void foo(char const * fmt, . ..)
并且通常fmt
提供有关参数数量的线索。最少有 1 个参数 (fmt)。
argc/argv stuff is not really variadic.
Variadic functions (such as
printf()
) use arguments put on the stack, and don't require at least 2 arguments, but 1.You have
void foo(char const * fmt, ...)
and usuallyfmt
gives a clue about the number of arguments.That's minimum 1 argument (fmt).
C 的反射能力非常有限,因此您必须有某种方法来指示变量参数包含什么内容 - 指定参数的数量或参数的类型(或两者),这就是多一个参数背后的逻辑。它是 ISO C 标准所要求的,因此您不能省略它。如果您觉得不需要任何额外的参数,因为参数的数量和类型始终是常量,那么首先就不需要变量参数。
您当然可以设计其他方法来编码变量参数内的数字/类型信息,例如 哨兵值。如果你想这样做,你可以只为第一个参数提供一个虚拟值,而不是在方法体中使用它。
只是为了对你的标题迂腐,可变参数函数只需要一个参数(而不是两个)。在不提供任何可选参数的情况下调用可变参数函数是完全有效的:
C has very limited reflection abilities so you must have some way to indicate what it is that the variable arguments contain - either specifying the number of arguments or the type of them (or both), and that is the logic behind having one more parameter. It is required by the ISO C standard so you can't omit it. If feel you don't need any extra parameters because the number and type of the arguments is always constant then there is no need for variable arguments in the first place.
You could of course design other ways to encode the number / type information inside the variable arguments such as a sentinel value. If you want to do this, you can just supply a dummy value for the first argument and not use it in the method body.
And just to be pedantic about your title, variadic functions only require one argument (not two). It's perfectly valid to make a call to a variadic function without providing any optional arguments:
我认为,原因有以下几点:
在宏
va_start(list, param);
中,您指定最后一个固定参数 - 需要确定堆栈上变量参数列表的开头地址。I think, that the reason is the following:
in the macro
va_start(list, param);
you specify the last fixed argument - it is needed to determine the address of the beginning of the variable arguments list on the stack.那么您如何知道用户是否提供了任何参数?
必须有一些信息来表明这一点,而且 C 一般来说并不是为了进行背后的数据操作而设计的。所以你需要的任何东西,它都会让你明确地通过。
How would you then know if the user provided any arguments?
There has to be some information to indicate this, and C in general wasn't designed to do behind-your-back data manipulation. So anything you need, it makes you pass explicitly.
我确信如果您真的想要,您可以尝试强制执行某种方案,其中可变参数函数仅采用某种类型的参数(例如整数列表) - 然后您填充一些全局变量,指示您传递了多少个整数。
您的两个示例不是可变参数函数。它们是带有两个参数的函数,但它们也强调了类似的问题。在没有额外信息的情况下如何知道 C 数组的大小?您可以传递数组的大小,也可以使用一些界定数组末尾的标记值(即 C 字符串的“\0”)来描述方案。
在可变参数情况和数组情况下,您都遇到相同的问题,您如何知道您可以合法访问多少数据?如果你不知道数组的情况,你就会出界。如果你不知道可变参数的情况,你会调用 va_arg 太多次,或者使用错误的类型。
为了扭转这个问题,您如何能够实现一个采用可变数量参数而不传递额外信息的函数?
I'm sure if you really wanted to you could try to enforce some scheme whereby the variadic function takes only a certain type of parameter (a list of ints for example) - and then you fill some global variable indicating how many ints you had passed.
Your two examples are not variadic functions. They are functions with two arguments, but they also highlight a similar issue. How can you know the size of a C array without additional information? You can either pass the size of the array, or you describe a scheme with some sentinel value demarcating the end of the array (i.e. '\0' for a C string).
In both the variadic case and the array case you have the same problem, how can you know how much data you have legitimate access to? If you don't know this with the array case, you will go out of bounds. If you don't know this with the variadic case you will call va_arg too many times, or with the wrong type.
To turn the question around, how would you be able to implement a function taking a variable number of arguments without passing the extra information?