开发者

stdarg and NULL arguments

开发者 https://www.devze.com 2023-04-05 16:05 出处:网络
I want a function that, when called with a varying number of arguments, return the first non-NULL one. I\'ve tried this, but it core dumps on for loop:

I want a function that, when called with a varying number of arguments, return the first non-NULL one. I've tried this, but it core dumps on for loop:

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"


args is not an array of arguments. It's just the first argument you passed to first. So its value in this case is the value of q.

You can't iterate over va args like you are doing.

Do this:

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

This will crash if you have no non-NULL argument, though, so you would better pass the number of arguments as first argument:

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

Alternatively, use a sentinel:

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);
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号