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. It also notes instantiated form at (struct structure *)
and struct structure *
. This, what seems to be getting assigned to s
is int (struct structure *)
.
It compiles fine when parentheses are removed from (struct structure *)
, but the structures that are supposed to be initialized are inaccessible.
Why is int
assumed when parentheses are around the type argument passed to va_arg? 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. 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. 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:
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.
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With