简体   繁体   English

带指针的va_arg

[英]va_arg with pointers

I want to initialize a linked list with pointer arguments like so: 我想用指针参数初始化一个链表,如下所示:

/* 
 * 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;
}

The problem is that clang errors type name requires a specifier or qualifier at va_arg(va, (struct structure *)) , and says that the type specifier defaults to int. 问题是clang错误type name requires a specifier or qualifier va_arg(va, (struct structure *)) type name requires a specifier or qualifier va_arg(va, (struct structure *)) ,并且说类型说明符默认为int。 It also notes instantiated form at (struct structure *) and struct structure * . 它还注意到(struct structure *)struct structure *实例化形式。 This, what seems to be getting assigned to s is int (struct structure *) . 这似乎是分配给sint (struct structure *)

It compiles fine when parentheses are removed from (struct structure *) , but the structures that are supposed to be initialized are inaccessible. 当从(struct structure *)中删除括号时,它编译得很好,但是应该初始化的结构是不可访问的。

Why is int assumed when parentheses are around the type argument passed to va_arg? 为什么在括号围绕传递给va_arg的类型参数时假设为int How can I fix this? 我怎样才能解决这个问题?

va_arg is a macro on many systems, and evidently the parentheses around struct structure * causes the macro to expand so something unparseable. va_arg是许多系统上的宏,显然围绕struct structure *的括号会导致宏扩展,因此无法解析。 So don't do that. 所以不要这样做。

This has nothing to do with the reason that your initialized structures are "inaccessible". 这与您的初始化结构“无法访问”的原因无关。 You are allocating structures and assigning them to s , but s is a local variable. 您正在分配结构并将它们分配给s ,但s是局部变量。 You can't affect a value in the caller by assigning to a local variable. 您不能通过分配局部变量来影响调用者中的值。 To accomplish what you want to do, the caller needs to pass a pointer-to-a-pointer, which you can then initialize 要完成你想要做的事情,调用者需要传递一个指向指针的指针,然后你可以初始化它

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

And the caller should do: 调用者应该这样做:

struct structure *a, *b;
init_structures(&a, &b, NULL);

§7.15.1.1 (The va_arg macro) of C99 requires: C99的 §7.15.1.1( va_arg宏)要求:

The parameter type shall be a type name specified such that the type of a pointer to an object that has the specified type can be obtained simply by postfixing a * to type. 参数类型应该是一个特定的类型名称,这样只需通过将a *固定为类型就可以获得指向具有指定类型的对象的指针类型。

That is why parentheses are not permitted here. 这就是为什么这里不允许使用括号的原因。

Other answers have explained why you need to pass in struct structure ** and assign the malloc result to *s . 其他答案解释了为什么需要传入struct structure **并将malloc结果赋给*s

You can't put parens around the type in va_arg . 你不能在va_arg的类型周围放置parens。 You don't need to. 你不需要。 va_arg is a strange beast. va_arg是一个奇怪的野兽。 Practically, it's a CPP macro that expands into some sort of per-compiler magic. 实际上,它是一个CPP宏,可以扩展到某种编译器时的魔力。 If you look at the expansion of it with your compiler, you will see how your compiler does it. 如果您使用编译器查看它的扩展,您将看到编译器如何执行它。 Whatever it is, it don't like parens. 无论是什么,它都不喜欢parens。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM