6

我想用指针参数初始化一个链表,如下所示:

/* 
 * Initialize a linked list using variadic arguments
 * Returns the number of structures initialized
 */
int init_structures(struct structure *first, ...) 
{
    struct structure *s;
    unsigned int count = 0;
    va_list va;
    va_start(va, first);

    for (s = first; s != NULL; s = va_arg(va, (struct structure *))) {
        if ((s = malloc(sizeof(struct structure))) == NULL) {
            perror("malloc");
            exit(EXIT_FAILURE);
        }
        count++;
    }

    va_end(va);

    return count;
}

问题是 , 的 clang 错误type name requires a specifier or qualifierva_arg(va, (struct structure *))并说类型说明符默认为 int。它还记录了(struct structure *)和的实例化形式struct structure *。这个,似乎被分配到s的是int (struct structure *).

当从 中删除括号时,它编译得很好(struct structure *),但是应该初始化的结构是不可访问的。

int当括号围绕传递给 va_arg 的类型参数时,为什么假定?我怎样才能解决这个问题?

4

3 回答 3

7

va_arg是许多系统上的宏,显然周围的括号struct structure *会导致宏扩展,因此无法解析。所以不要那样做。

这与您的初始化结构“不可访问”的原因无关。您正在分配结构并将它们分配给s, 但s它是一个局部变量。您不能通过分配给局部变量来影响调用者中的值。为了完成你想做的事情,调用者需要传递一个指向指针的指针,然后你可以初始化它

int init_structures(struct structure **first, ...) 
{
    struct structure **s;
    unsigned int count = 0;
    va_list va;
    va_start(va, first);

    for (s = first; s != NULL; s = va_arg(va, struct structure **)) {
        if ((*s = malloc(sizeof(struct structure))) == NULL) {
            perror("malloc");
            exit(EXIT_FAILURE);
        }
        count++;
    }

    va_end(va);

    return count;
}

调用者应该这样做:

struct structure *a, *b;
init_structures(&a, &b, NULL);
于 2010-05-16T22:03:54.453 回答
5

C99的 §7.15.1.1(va_arg宏)要求:

参数类型应该是一个指定的类型名称,这样指向具有指定类型的对象的指针的类型可以简单地通过在类型后面加上 * 来获得。

这就是为什么这里不允许使用括号。

其他答案已经解释了为什么您需要传入struct structure **并将 malloc 结果分配给*s.

于 2010-05-16T22:08:34.733 回答
1

你不能在类型周围加上括号 va_arg。你不需要。va_arg是一头奇异的野兽。实际上,它是一个 CPP 宏,可以扩展为某种针对每个编译器的魔法。如果你用你的编译器看它的扩展,你会看到你的编译器是怎么做的。不管是什么,它都不喜欢括号。

于 2010-05-16T22:03:50.550 回答