为什么我必须在c int
函数中使用var_args
类型的变量?像printf
一样,它是一个内置函数,不需要在输入各种变量之前声明参数的长度...
答案 0 :(得分:1)
C标准不需要带有可变参数列表的函数来具有任何特定的参数类型。
但是,取决于对va_arg
进行适当调用的功能。为此,该函数必须具有某种方式来知道已传递了哪些参数。您可以按照自己希望的任何方式实现该要求,包括:
printf
一样,使用包含表示参数类型的转换说明符的格式字符串。open
调用可能带有标志,该标志指示应创建文件还是仅打开现有文件。如果要创建文件,则可以使用一个附加参数,指示要在该文件上设置的权限,而如果仅打开现有文件,则不采用该参数。答案 1 :(得分:1)
C不允许变量参数函数选择采用零参数。也就是说,...
之前必须有一个命名参数。
对于printf
,命名参数是格式字符串。解析格式字符串时,可以推导出下一个参数的类型,并且可以正确调用va_arg
宏。
如果所有参数的类型相同,则可以使用命名参数指示要传入的参数的数量。例如,如果要传入许多字符串:
void foo_strings (int n, ...) {
va_list ap;
va_start(ap, n);
while (n--) {
const char *s = va_arg(ap, const char *);
foo(s);
}
va_end(ap);
}
但是,您可以很容易地使用NULL
来指示没有更多的字符串。然后,第一个参数可以用于其他功能,例如指向函数。
void foo_string (void (*foo)(const char *), ...) {
va_list ap;
va_start(ap, n);
const char *s = va_arg(ap, const char *);
while (s != NULL) {
foo(s);
s = va_arg(ap, const char *);
}
va_end(ap);
}
答案 2 :(得分:1)
答案与编译器调用约定有关。这是一个稍微简化的解释:
基本上,当编译器遇到带有N个参数的函数调用时,它将生成将N个参数压入堆栈的代码。
当编译器编译一个带有N个参数的函数时,它会生成代码以将N个参数弹出堆栈。
没有“秘密”信息告诉函数推入了多少个参数。对于普通函数,参数的数量和类型是一致的,仅是因为调用代码中的函数原型与函数定义一致。
对于可变函数,不可能依赖函数定义。 ...
的字面意思是“我们不知道要推送哪些参数。因此,需要为参数说明提供一个替代来源。一种简单的实现方式是确保第一个参数是固定计数-size个参数。
printf
和家人使用不同的方法。格式字符串定义了它将使用的类型和多少个参数。