stdarg和NULL参数

Ale*_*sky 4 c variadic-functions

我想要一个函数,当使用不同数量的参数调用时,返回第一个非NULL函数.我试过这个,但它for循环核心转储:

char *first(char *args, ...)
{
    va_list ap;
    char *r = NULL, *p;

    va_start(ap, args);
    for (p = args; *p; p++) {
        r = va_arg(ap, char*);
        if (r != NULL) break;
    }
    va_end(ap);
    return r;
}

char *q = NULL;
char *w = NULL;
char *e = "zzz";
char *r = NULL;
printf("%s\n", first(q, w, e, r)); // ought to print "zzz"
Run Code Online (Sandbox Code Playgroud)

Arn*_*anc 11

args不是一个参数数组.这只是你传递给的第一个参数first.所以它在这种情况下的价值是q.

你不能像你正在做的那样迭代 va args.

做这个:

va_start(ap, args);
do {
    r = va_arg(ap, char*);
    if (r != NULL) break;
} while (1);
va_end(ap);
Run Code Online (Sandbox Code Playgroud)

但是,如果没有非NULL参数,这将会崩溃,因此您最好将参数数量作为第一个参数传递:

char *first(int nargs, ...)
{
    char *r = NULL;

    va_start(ap, nargs);
    for( ; nargs; nargs--) {
        r = va_arg(ap, char*);
        if (r != NULL) break;
    }
    va_end(ap);

    return r;
}

first(4, q, w, e, r);
Run Code Online (Sandbox Code Playgroud)

或者,使用哨兵:

char *first(char *first, ...)
{
    char *r = first;

    va_start(ap, first);
    while (!r) {
        r = va_arg(ap, char*);
    }
    va_end(ap);

    return r == &sentinel ? NULL : r;
}

char sentinel; // its address is unique among other pointers

first(q, w, e, r, &sentinel);
Run Code Online (Sandbox Code Playgroud)