2010-05-16 8 views
3

Je veux initialiser une liste chaînée avec des arguments de pointeur comme ceci:va_arg avec des pointeurs

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

Le problème est que les erreurs de Clang type name requires a specifier or qualifier à va_arg(va, (struct structure *)), et dit que les paramètres par défaut de spécificateur de type int *. Il note également la forme instanciée à (struct structure *) et struct structure *. Ceci, ce qui semble être affecté à s est int (struct structure *).

Il compile bien lorsque les parenthèses sont retirées de (struct structure *), mais les structures qui sont censées être initialisées sont inaccessibles.

Pourquoi est-ce que int est supposé lorsque des parenthèses sont autour de l'argument de type passé à va_arg? Comment puis-je réparer cela?

Répondre

5

va_arg est une macro sur de nombreux systèmes, et évidemment les parenthèses autour de struct structure * provoquent l'expansion de la macro donc quelque chose d'impossible à analyser. Alors ne fais pas ça.

Ceci n'a rien à voir avec la raison pour laquelle vos structures initialisées sont "inaccessibles". Vous allouez des structures et vous les affectez à s, mais s est une variable locale. Vous ne pouvez pas affecter une valeur dans l'appelant en l'affectant à une variable locale. Pour accomplir ce que vous voulez faire, l'appelant doit passer un pointeur à un pointeur, que vous pouvez ensuite initialiser

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

Et l'appelant doit faire:

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

'va_arg' est requis pour être une macro. –

1

Vous ne pouvez pas mettre les parens autour du type va_arg. Vous n'en avez pas besoin. va_arg est une bête étrange. Pratiquement, c'est une macro CPP qui se développe dans une sorte de magie par compilateur. Si vous regardez l'expansion de celui-ci avec votre compilateur, vous verrez comment votre compilateur le fait. Quoi qu'il en soit, il n'aime pas les parens.

4

§7.15. 1.1 (la va_arg macro) de C99 nécessite:

le paramètre de type est un nom spéci fi ée de type telle que la Le type d'un pointeur sur un objet qui a le type spéci fi é peut être obtenu simplement par en post-fixant un * au type.

C'est pourquoi les parenthèses ne sont pas autorisées ici.

D'autres réponses ont expliqué pourquoi vous devez transmettre struct structure ** et affecter le résultat malloc à *s.

Questions connexes