【问题标题】:In C, how do we force the last argument in a varargs function to be a terminating null?在 C 中,我们如何强制可变参数函数中的最后一个参数为终止空值?
【发布时间】:2018-01-24 16:00:32
【问题描述】:

在 C++ 中,我们可能会这样写:

#include <cassert.h>
#include <cstdio.h>
#include <cstdarg.h>

void func(..., short end = 0) {

   // prevent caller from overriding default value with something other than null 
   assert(end == 0);

   va_list args;  

   short x;
   x = va_arg(args, short); 

   while (x != 0) {
       printf("%d", va_arg(args, short));
   }

   va_end(list);

   return;
}

但是,C 不支持默认函数参数。有什么办法可以强制func 在其参数列表的末尾有一个尾随空字符?有没有办法让程序员不显式地将终止的 null 传递给函数?

我们不希望看到如下调用:

int   x = 5;
float y = 6.4;
func(x, y, 0);

我们只想要func(x, y);

是否可以编写一个可以转换文本的宏

func(x, y);

进入通话:

func(x, y, 0);?

有没有什么方法可以在没有宏的情况下做到这一点?

【问题讨论】:

  • 如果你想将函数参数固定为某个常数值,那么它可能一开始就不应该是参数。
  • 简答 -> 你不能。长答案->你仍然不能。
  • 嗯,这也不是有效的 C++。

标签: c function variadic-functions default-arguments


【解决方案1】:

您不能强制可变参数函数在 C 中具有特定的“最后一个”值。

参数列表中需要有一些东西告诉函数有多少参数。标准库中的一些示例:

  • printf:格式字符串告诉函数有多少个参数以及它们的类型。
  • execl:接受多个 const char * 参数,最后一个参数必须是 NULL

因此,在调用 varargs 函数时将“标志”参数作为最后一个参数是 C 中已知的编程范例。这不是您需要掩盖的东西。


话虽如此,你可以使用宏来做你想做的事:

#define FUNC(...) func(__VA_ARGS__, 0)

宏参数列表中的... 捕获所有参数,而__VA_ARGS__ 宏表示这些参数。

然后你可以像这样定义func

void func(short first, ...)

然后像这样通过宏调用它

FUNC(x, y);

【讨论】:

  • 您不需要定义具有不同名称的宏。如果宏扩展到自身,则它会停止扩展。如果您在示例中将其称为 func ,那么它将对函数的用户透明。
【解决方案2】:

这不是 C 可变参数的用途,因此很难让它们以这种方式工作。应该有一个强制性的前导参数,您可以从中推断出以下参数的数量和类型。格式字符串填补了 printf 系列函数的这个角色。你可以取一个整数作为参数的数量,并在函数名中编码类型。

funcs(int num, ...); // s for short

不过,这不会提供任何类型强制。编译器仍将允许传递非短裤。没有办法通过可变参数强制类型。此时不妨使用经典的数组和计数习语。

funcs(int num, short const*);

【讨论】:

    【解决方案3】:

    #define func(x,y,z) func(x,y) 应该作为宏工作,但是您想要的(具有相同函数名称的不同数量的参数)在 C 中是不可能的。 你也可以有一个函数,在其中传递一个数组,其中包含参数和参数数量作为整数,然后你可以根据给出的参数数量做不同的事情。

    【讨论】:

    • 问题是关于可变参数的使用。
    • 那为什么我会读到:“是否可以编写一个宏来转换像 [...] 这样的文本”?这个问题似乎更多的是关于 C 中的多态性表达,而不是关于 varargs。
    • 查看帖子标题
    猜你喜欢
    • 2017-11-24
    • 2018-05-31
    • 1970-01-01
    • 1970-01-01
    • 2011-02-19
    • 2013-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多