关于gnu's C的文档指出如果函数具有__attribute__((sentinel))
它必须具有NULL
作为该函数的最后一个参数。如何使用自定义标记值创建可变参数函数?
是否可以有任何其他值作为结束参数列表的标记?
关于gnu's 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;
}
使用GCC的'__attribute __((sentinel))'编译器_can_检查参数列表是否以给定的值结束。只是它允许的唯一值是'NULL' - 它不会让您为编译器选择另一个值来验证。 –
如果他只是想知道是否有像__attribute __((sentinel))这样的任意哨兵值,那么答案就没有那么有用了,但是如果关于__attribute __((sentinel))的东西留下了印象非空哨兵根本无法使用,它应该清除它。 – Dmitri
这是(经过编辑下来的版本)苹果如何定义得心应手NS_REQUIRES_NIL_TERMINATION
预编译检查,即需要一些方法的零定点...
+ (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
不太清楚的differenc e是在这两个编译器指令之间..但我认为这个结构可以与“其他”,“定制”哨兵一起使用..我在想NSNotFound
- XX_REQUIRES_NSNOTFOUND_TERMINATION
或类似的东西?
至于创建这样的功能,显然你可以做到这一点。我不知道任何GNU扩展,以检查任意可变参数方案的参数是否正确。他们甚至没有一个属性可以将参数标记为给出了多少个参数的“计数”,以便编译器可以检查它们是否正确。 –