C语言 如何创建具有自定义前哨值的可变函数



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;
}

这是Apple如何定义方便的NS_REQUIRES_NIL_TERMINATION预编译检查的(编辑后的版本),即要求用某些方法设置nil哨兵…

+ (NSArray*)arrayWithRects:(NSR)rect,...NS_REQUIRES_NIL_TERMINATION;

#if !defined(NS_REQUIRES_NIL_TERMINATION)
 #if defined(__APPLE_CC__) && (__APPLE_CC__ >= 5549)
  #define NS_REQUIRES_NIL_TERMINATION __attribute__((sentinel(0,1)))
 #else
  #define NS_REQUIRES_NIL_TERMINATION __attribute__((sentinel))
 #endif
#endif

不太确定这两个编译器指令之间的区别是什么…但我认为这个结构可以与"其他"、"自定义"哨兵一起使用。我想NSNotFound - XX_REQUIRES_NSNOTFOUND_TERMINATION或类似的东西?

相关内容

  • 没有找到相关文章

最新更新