9

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

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

4

2 回答 2

4

您可以使用任何想要标记参数列表末尾的值,只要您对它有足够的了解即可从参数列表中抓取它。但是,编译器通常不会检查您选择的值是否在调用函数时实际传递,因此您需要注意它。

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

例如:

#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;
}
于 2011-10-03T18:07:45.077 回答
0

这是 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或者类似的东西?

于 2013-06-29T14:37:16.243 回答