【问题标题】:Why variadic functions require at least two arguments?为什么可变参数函数至少需要两个参数?
【发布时间】:2011-10-02 08:17:40
【问题描述】:

我正试图填补我知识中的一个漏洞。为什么可变参数函数至少需要两个参数?主要来自 C 的 main 函数,将 argc 作为参数计数,然后将 argv 作为字符数组的数组?此外,Objective-C 的 Cocoa 具有 NSString 方法,这些方法需要格式作为第一个参数,然后是参数数组 ([NSString stringWithFormat:@"%@", foo])。为什么不可能创建一个只接受参数列表的可变参数函数?

【问题讨论】:

    标签: c variadic-functions


    【解决方案1】:

    argc/argv 的东西并不是真正的可变参数。

    可变参数函数(例如printf())使用放在堆栈上的参数,并且不需要至少 2 个参数,但需要 1 个。

    您有void foo(char const * fmt, ...),通常fmt 会提供有关参数数量的线索。 这是至少 1 个参数 (fmt)。

    【讨论】:

      【解决方案2】:

      C 的反射能力非常有限,因此您必须有某种方法来指示变量参数包含的内容 - 指定参数的数量或它们的类型(或两者),这就是拥有一个背后的逻辑更多参数。它是 ISO C 标准所要求的,因此您不能省略它。如果觉得不需要任何额外的参数,因为参数的数量和类型始终是常量,那么首先就不需要可变参数。

      您当然可以设计其他方法来编码变量参数中的数字/类型信息,例如sentinel value。如果你想这样做,你可以只为第一个参数提供一个虚拟值,而不是在方法体中使用它。

      只是为了对你的标题迂腐,可变参数函数只需要 一个 参数(而不是两个)。在不提供任何可选参数的情况下调用可变参数函数是完全有效的:

      printf("Hello world");
      

      【讨论】:

      • 嗯,如果你仍然使用哨兵,你不能让第一个参数与哨兵的类型相同,并安排你的循环,使第一个参数值不来自va_list?这并不像没有参数的调用实际上首先是有效的,因为无论如何你总是需要哨兵。
      【解决方案3】:

      我认为,原因如下: 在宏 va_start(list, param); 中,您指定最后一个固定参数 - 需要确定堆栈上变量参数列表的开头地址。

      【讨论】:

        【解决方案4】:

        那么您如何知道用户是否提供了任何参数?

        必须有 一些 信息来表明这一点,而 C 通常不是为进行背后的数据操作而设计的。所以你需要的任何东西,它都会让你明确地通过。

        【讨论】:

          【解决方案5】:

          我敢肯定,如果你真的想要,你可以尝试执行一些方案,其中可变参数函数只接受某种类型的参数(例如整数列表) - 然后你填充一些全局变量来指示有多少个整数你已经通过了。

          您的两个示例不是可变参数函数。它们是带有两个参数的函数,但它们也突出了一个类似的问题。如果没有其他信息,您如何知道 C 数组的大小?您可以传递数组的大小,也可以使用一些标记值来定义数组的结尾(即 C 字符串的“\0”)。

          在可变参数情况和数组情况下,您都有同样的问题,您如何知道您可以合法访问多少数据?如果您不知道数组案例的这一点,那么您将超出界限。如果你不知道可变参数的情况,你会调用 va_arg 太多次,或者使用错误的类型。

          为了扭转这个问题,你如何能够实现一个函数来获取可变数量的参数而不传递额外的信息?

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-02-24
            • 1970-01-01
            • 1970-01-01
            • 2017-02-08
            • 2011-10-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多