28 votes

Que signifie ... une liste d'arguments en C?

Je suis tombé sur la signature de fonction suivante et je me suis demandé si cela (les points de suspension, ou "..." ) était une sorte de polymorphisme?

 #include <fcntl.h>
int fcntl(int fd, int cmd, ... );
 

Merci d'avance.

19voto

uniquesnowflake8 Points 275

14voto

Joe Chung Points 6263

C'est une fonction variadique . Voir stdarg.h pour plus de détails.

10voto

rix0rrr Points 4924

L' ... signifie que vous pouvez passer n'importe quel nombre d'arguments de cette fonction, comme d'autres commentateurs l'ont déjà mentionné. Puisque les arguments facultatifs ne sont pas typés, le compilateur ne peut pas vérifier les types et vous pouvez techniquement passer un argument de n'importe quel type.

Donc, est-ce à dire que vous pouvez l'utiliser pour mettre en œuvre une sorte de fonction polymorphe? (I. e., une fonction qui effectue une opération basée sur le type de ses arguments.)

Pas de.

La raison vous ne pouvez pas faire cela, c'est parce que vous ne pouvez pas lors de l'exécution d'inspecter les types d'arguments transmis. La fonction de lecture dans la liste d'arguments variable devrait déjà connaître le type des arguments optionnels il va recevoir.

Dans le cas d'une fonction qui est vraiment censé être capable de prendre n'importe quel nombre d'arguments de tout type (c'est à dire, printf), les types d'arguments sont transmis via la chaîne de format. Cela signifie que l'appelant a pour spécifier les types, il va se passer à chaque invocation, de retirer le bénéfice de fonctions polymorphes (que l'appelant n'a pas à connaître les types de soit).

Comparer:

// Ideal invocation
x = multiply(number_a, number_b)
y = multiply(matrix_a, matrix_b)

// Standard C invocation
x = multiply_number(number_a, number_b)
y = multiply_matrix(matrix_a, matrix_b)

// Simulated "polymorphism" with varargs
x = multiply(T_NUMBER, number_a, number_b)
y = multiply(T_MATRIX, matrix_a, matrix_b)

Vous devez spécifier le type avant de les varargs fonction peut faire la bonne chose, si cela vous rapporte rien.

8voto

Lasse V. Karlsen Points 148037

Non, ce sont les "points de suspension" que vous voyez là, en supposant que vous faites référence à la partie ... de la déclaration.

Fondamentalement, il dit que cette fonction prend un nombre inconnu d'arguments après les deux premiers qui y sont spécifiés.

La fonction doit être écrite de telle manière qu'elle sache à quoi s'attendre, sinon des résultats étranges s'ensuivent.

Pour les autres fonctions qui prennent en charge cela, regardez la fonction printf et ses variantes.

6voto

dfa Points 54490

Est-ce que C de soutenir le polymorphisme? Non, il n'est pas.

Cependant, il existe plusieurs bibliothèques, tels que le Python API C qui implémente un accidenté de la variante de polymorphisme à l'aide de structures et pointeurs. Attention, le compilateur ne peut pas effectuer le type approprié de vérifier dans la plupart des cas.

La tecnhique est simple:

typedef struct {
    char * (*to_string)();
} Type;

#define OBJ_HEADER Type *ob_type

typedef struct {
    OBJ_HEADER;
}  Object; 

typedef struct {
    OBJ_HEADER;
    long ival;        
} Integer;

typedef struct {
    OBJ_HEADER;
    char *name;
    char *surname;
} Person;

Entier et Personne d'obtenir un objet de Type approprié avec des pointeurs de fonction (par exemple, des fonctions telles que integer_to_string et person_to_string).

Maintenant, il suffit de déclarer une fonction acceptant un Objet *:

void print(Object *obj) {
    printf("%s", obj->type->to_string());
}

maintenant, vous pouvez appeler cette fonction avec à la fois un nombre Entier et d'une Personne:

Integer *i = make_int(10);
print((Object *) i);

Person *p = make_person("dfa");
print((Object *) p);

MODIFIER

sinon, vous pouvez déclarer i et p comme Objet *; bien sûr make_int et make_person va allouer de l'espace pour l'Entier et Personne et ne appropriés cast:

Object * 
make_integer(long i) {
     Integer *ob = malloc(sizeof(Integer));
     ob->ob_type = &integer_type;
     ob->ival = i;
     return (Object *) ob;
}

NB: je ne peut pas compiler ces exemples droite maintenant, veuillez communiquer entre eux.

Je suis tombé sur la fonction suivante signature et je me demandais si cela (les points de suspension, ou "...") est une sorte de polymorphisme?

oui, c'est une forme primitive de polymorphisme. Avec une seule signature de fonction vous êtes en mesure de passer les différentes structures. Cependant, le compilateur ne peut pas vous aider à la détection d'erreurs de type.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X