关于gnu的C的文档说明如果函数有__attribute__((sentinel))
,它必须有NULL
作为函数的最后一个参数。
是否可以将任何其他值作为结束参数列表的标记?
答案 0 :(得分: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
,则可能会发生错误。
另一个带指针的例子,其中一个sentinel节点作为第一个传递,另一个作为最后一个参数传递:
/* 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;
}
答案 1 :(得分: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
- {{1}或类似的东西?