TUTORIAL: Pass nombre variable d'arguments à une fonction C

  • spork
  • Brewmaster
  • Silver Member
  • Avatar de l’utilisateur
  • Inscription: Sep 22, 2003
  • Messages: 6130
  • Loc: Seattle, WA
  • Status: Offline

Message Mars 27th, 2009, 11:07 am

Introduction


Note: Le code source complet pour l'exemple dans ce tutoriel peut être téléchargée à la fin du tutoriel.

Note: Essayer de faire dans la PHP ? Check this out .

Lorsque vous déclarez une fonction, le type et le nombre d'arguments sont généralement fixés à la compilation. Mais il est parfois nécessaire pour une fonction de pouvoir accepter un certain nombre d'arguments variable inconnue jusqu'à l'exécution.

Ce tutoriel va vous montrer comment créer une fonction C qui peut accepter un nombre variable d'arguments.

In a Nutshell


Si vous cherchez tout simplement un exemple pour aller au large de, je ne vais pas vous faire attendre. Voici un exemple d'une somme en fonction () qui additionne tous les entiers qui lui est passé et renvoie la somme:

CPP Code: [ Select ]
#include <stdarg.h>
#include <stdio.h>
#include <stdarg.h>
 
int sum( int num, ... ) {
 
    va_list args;
    va_start(args, num);
 
    int i, total = 0;
    for( i = 0; i < num; ++i ) {
        total += va_arg(args, int);
    }
 
    va_end(args);
 
    return total;
}
 
int main() {
 
    int total = sum(5, 1, 2, 3, 4, 5);
    printf("Total: %d\n", total);
 
    return 0;
}
  1. #include <stdarg.h>
  2. #include <stdio.h>
  3. #include <stdarg.h>
  4.  
  5. int sum( int num, ... ) {
  6.  
  7.     va_list args;
  8.     va_start(args, num);
  9.  
  10.     int i, total = 0;
  11.     for( i = 0; i < num; ++i ) {
  12.         total += va_arg(args, int);
  13.     }
  14.  
  15.     va_end(args);
  16.  
  17.     return total;
  18. }
  19.  
  20. int main() {
  21.  
  22.     int total = sum(5, 1, 2, 3, 4, 5);
  23.     printf("Total: %d\n", total);
  24.  
  25.     return 0;
  26. }


How It Works


Regardons le code ligne par ligne:

CPP Code: [ Select ]
#include <stdarg.h>

La bibliothèque stdarg nous fournit les va_list type de données, ainsi que les macros va_start , va_arg , Et va_end pour manipulation de la liste d'arguments.

CPP Code: [ Select ]
int sum( int num, ... ) {

Pour déclarer la fonction, nous utilisons un point triple (...) Pour indiquer que la fonction accepte un nombre variable d'arguments. Le premier argument, num , Est utilisé pour indiquer combien d'arguments ont été adoptés dans la fonction.

Si nous ne voulons pas utiliser l'argument d'abord comme une indication de longueur argument, nous aurions pu simplement utilisé le premier argument dans le cadre du numérotées pour se résumer, et a ensuite utilisé une sorte de numéro spécial (un négatif, peut-être) comme un indicateur que le dernier argument a été atteint.

CPP Code: [ Select ]
va_list args;

va_list est un type de données utilisées par stdarg pour contenir la liste des arguments passés dans la fonction. Ici, nous déclarons une variable appelée args .

CPP Code: [ Select ]
va_start(args, num);

va_start est une macro utilisé pour initialiser la liste des arguments pour que nous puissions commencer à lire les arguments de là.

CPP Code: [ Select ]
int i, total = 0;
for( i = 0; i < num; ++i ) {
    total += va_arg(args, int);
}
  1. int i, total = 0;
  2. for( i = 0; i < num; ++i ) {
  3.     total += va_arg(args, int);
  4. }

Ici, on boucle sur la liste des arguments jusqu'au weve lire autant comme indiqué dans notre premier argument. va_arg la macro est utilisé pour lire un argument sur la liste. Elle prend deux paramètres: le va_list objet nous avons créé, args , Et un type de données. va_arg retournera l'argument suivant, car ce type.

CPP Code: [ Select ]
va_end(args);

va_end est une autre macro qui nettoie nos args objet pour nous quand ont fini de l'utiliser.

CPP Code: [ Select ]
return total;

Enfin, nous revenons, nous avons calculé le total dans la fonction.

Conclusion


Vous devriez maintenant savoir comment créer une fonction C qui accepte un nombre variable d'arguments à l'exécution. Cette technique est particulièrement utile pour créer des fonctions wrapper pour les fonctions qui acceptent déjà un certain nombre d'arguments variable, comme printf (). Cela est démontré dans mon tutoriel d'autres, Rédaction d'un printf () personnalisée Wrapper fonction en C .

J'ai toujours les bienvenus questions ou des commentaires sur ce tutoriel. Il suffit de poster une réponse ou PM moi, im glad to help!
Attachments:
MultipleArgumentsC.zip

(646 Octets) Téléchargé 367 fois

Complete source code for the sum() example used in this tutorial.

The Beer Monocle. Classy.
  • Anonymous
  • Bot
  • No Avatar
  • Inscription: 25 Feb 2008
  • Messages: ?
  • Loc: Ozzuland
  • Status: Online

Message Mars 27th, 2009, 11:07 am

  • joebert
  • Sledgehammer
  • Genius
  • No Avatar
  • Inscription: Fév 10, 2004
  • Messages: 13455
  • Loc: Florida
  • Status: Offline

Message Mars 27th, 2009, 12:30 pm

Je comprends tout sauf cette partie.

CPP Code: [ Select ]
int sum( int num, ... ) {


Serait-ce valable?

CPP Code: [ Select ]
int sum( ... ) {


Ou est-il avoir être un argument en tête suivi de l'ellipse que la seconde?

En outre, est-ce valable?

CPP Code: [ Select ]
int sum( int one, int two, ... ) {
Strong with this one, the sudo is.
  • spork
  • Brewmaster
  • Silver Member
  • Avatar de l’utilisateur
  • Inscription: Sep 22, 2003
  • Messages: 6130
  • Loc: Seattle, WA
  • Status: Offline

Message Mars 27th, 2009, 12:47 pm

Im glad you asked, j'ai oublié d'élaborer sur cet aspect.

Malheureusement, il doit y avoir au moins un argument nommé avant l'ellipse. Vous pouvez spécifier autant d'arguments nommé youd comme tant les points de suspension intervient après chacun d'eux.

Si vous spécifiez plus d'un argument de nom, le nom de l'argument passé comme second paramètre à va_start () doit être le dernier (extrême droite) a nommé argument. Par exemple:
CPP Code: [ Select ]
int sum( int first, int second, int third, ... ) {
    va_list args;
    va_start(args, [b]third[/b]);
  1. int sum( int first, int second, int third, ... ) {
  2.     va_list args;
  3.     va_start(args, [b]third[/b]);

Cela indique à va_start () où chercher pour l'argument sans nom en premier.
The Beer Monocle. Classy.
  • wrostek
  • Born
  • Born
  • No Avatar
  • Inscription: Nov 09, 2009
  • Messages: 1
  • Status: Offline

Message Novembre 9th, 2009, 11:15 am

J'ai vu cette va_arg bonne introduction, mais j'ai une question un peu hors sujet.
Ses déclarations concernant la trace. Ils sont basés sur printf et je tiens à les garder dans la version finale. Pour des raisons de performances, ils ne devraient dump pour une mémoire tampon circulaire. Sur le crash mai il être écrit dans un fichier ou est en quelque sorte générées dans le fichier de base.
Mais la mise en forme printf prend runtime trop. Im la recherche d'un moyen de recueillir uniquement les paramètres dans un tableau et memcpy au tampon anneau. An off-line helper mai faire la mise en forme de cette prise plus tard.
Est-il possible de substituer printf pour la version release en utilisant va_arg? Ou dois-je descendre à l'assembleur afin de recueillir cette information?

Merci d'avance de tout soupçon
Wolfgang R.
  • genux
  • Graduate
  • Graduate
  • Avatar de l’utilisateur
  • Inscription: Jan 22, 2010
  • Messages: 106
  • Loc: UK
  • Status: Offline

Message Janvier 22nd, 2010, 8:32 am

Nice post .. Parfois, vous ne devez vraiment avoir un nombre indéfini de paramètres à une fonction.
  • koehler
  • Born
  • Born
  • No Avatar
  • Inscription: Jan 19, 2011
  • Messages: 2
  • Status: Offline

Message Janvier 19th, 2011, 4:57 pm

Hey, je me demandais si vous pouvez l'utiliser dans la fonction main (). J'ai besoin d'accepter des paramètres lorsque le programme est exécuté. Comment pourrais-je m'y prendre? Au lieu d'être les paramètres dans le programme, les paramètres sont lorsqu'elle est exécutée à
. / Cw 1000 larry.cwo bob.cwo me.cwo
(Ps. 1000 est cycles pour exécuter le programme, tandis que les 3 autres sont les programmes à exécuter)
Comment voulez-vous obtenir les 3 programmes (et leurs noms) de tout cela?

Merci d'avance pour toute réponse!

Deana
  • spork
  • Brewmaster
  • Silver Member
  • Avatar de l’utilisateur
  • Inscription: Sep 22, 2003
  • Messages: 6130
  • Loc: Seattle, WA
  • Status: Offline

Message Janvier 19th, 2011, 5:52 pm

Thats effectivement la seule façon principale () accepte les arguments:

C Code: [ Select ]
int main(int argc, char *argv[]) {
 
}
  1. int main(int argc, char *argv[]) {
  2.  
  3. }


argc est le nombre d'arguments passés au programme (y compris le nom du programme lui-même

argv est un tableau de C-chaînes contenant les arguments eux-mêmes.

http://www.bing.com/search?q=main+arguments
The Beer Monocle. Classy.
  • koehler
  • Born
  • Born
  • No Avatar
  • Inscription: Jan 19, 2011
  • Messages: 2
  • Status: Offline

Message Janvier 19th, 2011, 6:32 pm

Alright. Awesome. Alors maintenant, si je voulais obtenir la taille de ces programmes qui ont été adoptées dans l'argument? J'ai essayé de sizeof (), mais im nouveau c, et que seul m'a donné la taille du type (char = 1). Y at-il un moyen d'obtenir la taille des programmes?
  • jaqulin
  • Born
  • Born
  • No Avatar
  • Inscription: Mar 21, 2011
  • Messages: 1
  • Status: Offline

Message Mars 21st, 2011, 1:23 pm

Article Nice!. Est-il possible de passer les paramètres extraits de va_list être passés comme arguments à une autre fonction dynamiquement?

pour exemple: Dans la fonction ci-dessous je veux extraire des paramètres args
et le transmettre à another_function fonction "num".

C Code: [ Select ]
int sum( int num, ... ) {
 
    va_list args;
    va_start(args, num);
 
    char buf[80];
    for( i = 0; i < num; ++i ) {
        buf[i]= va_arg(args, int);
    }
 
    another function(num,buf[0],buf[1]);
    va_end(args);
 
    return total;
}
  1. int sum( int num, ... ) {
  2.  
  3.     va_list args;
  4.     va_start(args, num);
  5.  
  6.     char buf[80];
  7.     for( i = 0; i < num; ++i ) {
  8.         buf[i]= va_arg(args, int);
  9.     }
  10.  
  11.     another function(num,buf[0],buf[1]);
  12.     va_end(args);
  13.  
  14.     return total;
  15. }

Afficher de l'information

  • Total des messages de ce sujet: 9 messages
  • Modérateur: Tutorial Writers
  • Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 5 invités
  • Vous ne pouvez pas poster de nouveaux sujets
  • Vous ne pouvez pas répondre aux sujets
  • Vous ne pouvez pas éditer vos messages
  • Vous ne pouvez pas supprimer vos messages
  • Vous ne pouvez pas joindre des fichiers
 
 

© 2011 Unmelted, LLC. Ozzu® est une marque déposée de Unmelted, LLC