c - 如何创建具有自定义标记值的可变参数函数?

标签 c variadic-functions sentinel

gnu C 的文档指出,如果函数有 __attribute__((sentinel)),它必须有 NULL 作为函数的最后一个参数。

是否可以使用任何其他值作为结束参数列表的标记?

最佳答案

您可以使用任何您想要标记参数列表末尾的值,前提是您足够了解它并从参数列表中获取它。不过,编译器通常不会检查您选择的值是否在调用函数时实际传递,因此您需要小心处理。

本质上,您只是以通常的方式创建一个可变参数函数,在函数内部,当您读取与您的标记匹配的参数时,您将停止读取参数——没有什么特别需要做的,但您需要知道参数的类型阅读。

例如:

#include <stdarg.h>

/* Count arguments up to the number 5 */
int countArgsTilFive(int first, ...)
{
  int res = 1;
  va_list ap;
  if (first == 5) return 0;
  va_start(ap,first);
  while (va_arg(ap,int) != 5) res++;
  va_end(ap);
  return res;
}

...将计算在 5 之前出现的所有参数。但是,如果您不在列表中的某处将 5 传递给它,或者如果您传递给它的参数不是 int,则可能会发生不好的事情。

另一个指针示例,其中一个哨兵节点作为第一个参数传递,并再次作为最后一个参数传递:

/* Count arguments, excluding the first, until the first occurs again */
int countPtrs(void *sentinel, ...)
{
  int res = 0;
  va_list ap;
  va_start(ap,sentinel);
  while (va_arg(ap,void *) != sentinel) res++;
  va_end(ap);
  return res;
}

关于c - 如何创建具有自定义标记值的可变参数函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7638365/

相关文章:

C++ 标记值的数据类型始终是 bool 值?对或错?

mysql - 使用尾随标记对 DBMS 存储值进行编码以检测截断/损坏;优点?缺点?备择方案?

c - 具有唯一结构作为参数 C 的 pthread

c++ - 可变函数包装器

c++ - std::forward 不能转换大括号括起来的初始值设定项列表

c++ - varargs(va_list va_start) 不适用于传递引用参数

c - 将值返回给 main 后输出发生变化! (请给出一个简单的修复)

c - 在C中如何按字节数进行转换?

使用分配的内存将整数复制到整数

Redis哨兵故障转移配置问题