我想用指针参数初始化链表,如下所示:
/*
* 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;
}
问题是type name requires a specifier or qualifier
处的clang错误va_arg(va, (struct structure *))
,并且说类型说明符默认为int。它还记录了(struct structure *)
和struct structure *
的实例化表单。这似乎分配给s
的内容是int (struct structure *)
。
当从(struct structure *)
中删除括号时,它编译得很好,但是应该初始化的结构是不可访问的。
当括号围绕传递给va_arg的类型参数时,为什么会假设int
?我该如何解决这个问题?
答案 0 :(得分:5)
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);
答案 1 :(得分:4)
§7.15.1.1(va_arg
宏)要求:
参数 type 应为类型 名称指定为a的类型 指向具有该对象的对象的指针 特定类型可以简单地获得 通过post fi xing a *来输入。
这就是为什么不允许使用括号的原因。
其他答案解释了为什么您需要传递struct structure **
并将malloc结果分配给*s
。
答案 2 :(得分:1)
你不能在va_arg
中的类型周围放置parens。你不需要。 va_arg
是一个奇怪的野兽。实际上,它是一个CPP宏,可以扩展到某种编译器时的魔力。如果您使用编译器查看它的扩展,您将看到编译器如何执行它。无论是什么,它都不喜欢parens。