我正试图堵住我的知识洞。为什么可变函数需要至少两个参数?主要来自C的main
函数,其中argc
作为参数计数,然后argv
作为字符数组的数组? Objective-C的Cocoa还有NSString
个方法,它们需要格式作为第一个参数,然后是一个参数数组([NSString stringWithFormat:@"%@", foo]
)。为什么不能创建仅接受参数列表的可变参数函数?
答案 0 :(得分:8)
argc / argv的东西并不是真正的变量。
可变参数函数(例如printf()
)使用放在堆栈上的参数,并且不需要至少2个参数,但是1。
您有void foo(char const * fmt, ...)
,通常fmt
会提供有关参数数量的线索。
那是最小的1个参数(fmt)。
答案 1 :(得分:3)
C具有非常有限的反射能力,所以你必须有一些方法来指示变量参数包含的内容 - 指定参数的数量或它们的类型(或两者),这是有一个的逻辑背后的逻辑更多参数。它是ISO C标准所要求的,因此您不能省略它。如果觉得你不需要任何额外的参数,因为参数的数量和类型总是不变的,那么首先不需要变量参数。
您当然可以设计其他方法来编码变量参数中的数字/类型信息,例如sentinel value。如果你想这样做,你可以为第一个参数提供一个虚拟值,而不是在方法体中使用它。
只是为了对你的标题迂腐,可变函数只需要一个参数(而不是两个)。在不提供任何可选参数的情况下调用可变参数函数是完全有效的:
printf("Hello world");
答案 2 :(得分:1)
我认为,原因如下:
在宏va_start(list, param);
中指定最后一个固定参数 - 需要确定堆栈上变量参数列表开头的地址。
答案 3 :(得分:0)
您如何知道用户是否提供了任何参数?
必须有一些信息来表明这一点,并且C通常不是为了进行背后数据操作而设计的。所以你需要的任何东西都会让你明确地通过。
答案 4 :(得分:0)
我确定你是否真的想要你可以尝试强制执行一些方案,其中可变参数函数只接受某种类型的参数(例如一个整数列表) - 然后你填充一些全局变量来指示有多少整数你已经过去了。
您的两个示例不是可变函数。它们是具有两个参数的函数,但它们也突出了类似的问题。如何在没有附加信息的情况下知道C阵列的大小?您既可以传递数组的大小,也可以描述一个带有一些标记数组末尾的标记值的方案(即C字符串的'\ 0')。
在可变参数案例和数组案例中,您遇到同样的问题,您如何知道您有多少合法访问的数据?如果您对阵列大小写不了解,那么您将超出范围。如果你不知道变量大小写的情况,你会多次调用va_arg,或者使用错误的类型。
要解决这个问题,您如何能够实现一个函数,该函数使用可变数量的参数而不传递额外信息?