Fonctions avec listes variables d'arguments
Bonjour à tous,
Je reviens sur le site pour solliciter les éclairages de développeurs en C. J'ai cherché en vain la possibilité du propager une liste variable d'arguments d'une fonction vers une autre.
Soit la suite des deux instructions suivantes fréquemment utilisées comme telles dans une mise en page :
Code:
1 2
| sprintf (zone , "x=%d - y=%d - z=%d" , x , y , z) ;
iret = fonction_A (a , b , c , attribut , zone) ; |
Il serait souhaitable, pour simplifier le travail du programmeur, de proposer directement un appel à une fonction plus élaborée comme suit :
Code:
iret = fonction_B( a , b , c , attribut , "x=%d - y=%d - z=%d", x , y , z) ;
Dans le passé, j'ai eu, une ou deux fois, l'occasion d'utiliser les listes variables d'arguments. Je pensais que, dans le cas présent, le problème était beaucoup plus simple puisque l'analyse du format était refilée à la fonction standard "sprintf". J'ai donc écrit :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| int fonction_B( a , b , c , attribut , format , va_alist)
int a, b, c ;
char attribut[] ;
char format[] ;
{
char zone[256] ;
va_list ap ;
va_start(ap , format) ; // liste variable après 'format'
sprintf (zone, format, ap ) ;
va_end(ap) ;
return (fonction_A( a , b , c , attribut , zone) ) ;
} |
La compilation et l'édition de liens se passent très bien mais l'exécution, sans erreur, n'est pas bonne.
Très sincèrement, je ne vois pas où je fais des erreurs. J'ai probablement mal interprété la documentation que j'ai pu glaner ça et là sur la Toile.
Je suis sous MinGW/Msys Windows. À son installation, MinGW n'avait pas incorporé le fichier d'entête "stdarg.h". J'en ai téléchargé plusieurs. Le seul qui ne provoque pas d'erreur à la compilation est celui ci-dessous :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #ifndef __STDARG_H
#define __STDARG_H
typedef void *va_list;
#define __size(x) ((sizeof(x)+sizeof(int)-1) & ~(sizeof(int)-1))
#define va_start(ap, parmN) ((void)((ap) = (va_list)((char *)(&parmN)+__size(parmN))))
#define va_arg(ap, type) (*(type *)(((*(char **)&(ap))+=__size(type))-(__size(type))))
#define va_end(ap) ((void)0)
#if !__STDC__
#define _va_ptr (...)
#endif
#endif |
La forme "int fonction_B( a , b , c , attribut , format , ...)" provoque une erreur à la compilation !...
Avez-vous une idée ?
Merci d'avance.
Cordialement.
Lou Papet
Il y a un tout petit progrès !....
Bonjour,
Citation:
Envoyé par
edgarjacobs
Hello,
Si tu veux propager un liste variable d'arguments, voici une manière de faire
Code:
1 2 3 4 5 6 7 8 9 10 11 12
| #include <stdarg.h>
void fct(type arg1,type arg2,const char *format,...) {
va_list args;
// do something with arg1 and arg2
....
va_start(args,format);
fct_with_va(format,args); // call function with variable list of args given by caller
va_end(args);
....
} |
J'ai téléchargé un autre fichier entête "stdarg.h". Maintenant, à la compile, la forme (...) ne provoque plus d'erreur et peut donc remplacer l'ancienne forme (va_alist).
En dehors de cela, ce que vous me proposez est identique à ce que j'ai écrit.
J'ai bien ajouté "const" mais cela n'a rien changé. L'argument "format" est bien à passer à la fonction "sprintf". La procédure doit savoir que c'est un "char*" que "sprintf" va analyser pour connaître les différents types d'arguments. Le nouveau prototype est celui_ci :
Code:
1 2 3 4 5 6 7 8 9 10 11
| int fonction_B( int a, int b, int c, char *attribut, const char *format , ...)
{
char zone[256] ;
va_list ap ;
va_start(ap, format) ; // liste variable après 'format' y compris
sprintf (zone, ap ) ;
va_end(ap) ;
return (fonction_A( a , b , c , attribut , zone) ) ;
} |
pour un appel
Code:
iret = fonction_B( a , b , c , attribut , "x=%d - y=%d - z=%d", x , y , z) ;
Malheureusement, le résultat n'est guère plus fructueux ... la fonction me sort des hiéroglyphes !...
Mais en cherchant encore un petit peu, on va peut-être y arriver !... Mais où est-ce que cela coince ????....
Pour mieux comprendre sous gdb, j'essaie d'écrire une petite fonction pour simuler 'sprintf' mais ça n'a pas l'air bien brillant pour le moment !...
Merci
Lou Papet
Non, bien au contraire !...
Bonsoir Matt_Houston,
Non, pas du tout. J'avais suivi ses conseils. Mais c'était avant que je retélécharge le dernier fichier entête 'stdarg.h" qui a d'ailleurs étrangement ressemblé au premier. Peut-être une erreur de téléchargement. Je n'ai pas trouvé pourquoi.
Eh oui !... l'installation du MinGW ne fournit pas ce fichier à partir du fichier d'installation "mingw-get-setup.exe". C'est la version "0.6.2 beta-20131004-1". J'ai regardé s'il y avait une version plus récente. Je suis toujours retombé sur la même.
Devant cette absence, je pense qu'il faut essayer d'agir, et tenter des solutions. Mais après avoir envoyé mon message à 18h 04, je suis revenu sur la proposition 'vsprintf()" fournie par dalfab et ça a marché. J'ai quand même tilté sur son info.
Votre message a anticipé ma réponse définitive. Pas assez rapide.... l'âge peut-être !....
Je marque donc le sujet comme résolu en vous remerciant beaucoup à tous.
Bien cordialement.
Lou Papet.
3 pièce(s) jointe(s)
Qu'es acò !... E bèn .. diguès adounc !....
J'ai suivi votre conseil d'utiliser MSYS2 pour remplacer l'antique MinGW que j'utilisais jusqu'à présent.
Depuis le 11 mai, date de votre proposition jusqu'à aujourd'hui, 15 mai, (pas tout le temps quand même !) je ne peux pas dire que c'est une grosse réussite alors que j'ai suivi les consignes comme indiquées dans la doc sans prendre la moindre initiative. Les installations se passent normalement : tout est installé par défaut car je suis incapable de trier avec Pacman. Avec ce dernier, c'est trop fastidieux de savoir ce que chaque paquet fait, à part quelques-uns.... donc un gros marteau-pilon pour écraser une petite mouche !... Je n'ai besoin en fait que de gcc, de gdb, des API's Windows et de la SDL-1.2.
Un petit retour pour montrer que je me trouve coincé entre MSYS-64bits et Msys-32bits :
- Installation de la MSYS2 64 bits :
Surprenant quand même : Lors de l'exécution de gcc, le loader demande la librairie partagée "msys-mpfr-6.dll" qui n'existe nulle part ailleurs dans les dossiers de la racine d'installation "msys64" alors que dans "/usr/bin" on trouve la bibliothèque "msys-mpfr-4.dll".
. - Installation de MSYS2 32 bits :
Surprenant aussi : même erreur qu'avec MSYS 64bits.
. - Installation de ConEmu :
Comme conseillé dans la doc et qui m'est apparue comme une console assez intéressante mais voilà, si elle marche sous MSYS-64bits, sous MSYS-32bits, elle provoque l'erreur ci-dessous :
D'ailleurs, il semble que, quelque soit le choix, c'est toujours la version 64 bits qui est installée !!!....
Installé, désinstallé puis (ré)installé à nouveau, même topo !...
Pour ce qui concerne la "msys-mpfr-6.dll", voici ce que j'ai pu glaner sur la Toile :
Possible fixes for msys-mpfr-6.dll errors.
- Re-Install the application that requires msys-mpfr-6.dll.
- Update the application to the latest version.
- Install all Windows updates and any available driver updates.
- Clean your registry and optimize your computer.
- Download and install msys-mpfr-6.dll.
|
Il faut donc aller chercher la bibliothèque partageable "msys-mpfr-6.dll" sur la Toile, encore faut-il la trouver (!!!....) ce qui reviendrait à bidouiller comme vous me l'avez un peu reproché avec le MinGW .... (qui, lui, marche correctement !....).
Je n'ai donc pas insisté car je pense que le produit n'est pas compatible avec Windows 7 bien qu'il était écrit "Windows 7 and later" !... Si ce n'est pas le cas, alors ce sont le développeurs dans leur tour d'ivoire qui n'ont pas fait ce qu'il faut. Quant à la compatibilité ascendante, on ne connait plus ça aujourd'hui. Pas à la portée d'un vulgum pecus en tout cas contrairement à MinGW !... Je me trompe peut-être ? Il faut dire que je suis d'une vielle école du siècle dernier imprégné de la culture IBM gros système.
C'est bien joli le "Pacman" mais alors quelle régression par rapport au Loading Package Manager "MinGW Installer" et même au "Synaptic" de Linux !...
Pour continuer mes petits développements personnels, je m'en retourne donc vers MinGW que j'ai bidouillé mais qui marche en essayant toutefois le produit gcc/gdb "MinGW-w64". Je vais voir si ça colle.
Pour le moment, je n'ai pas l'intention de changer de PC tant qu'il marche (7 ans passés) ni même d'installer Windows 10.
Cordialement.
Lou Papet
Bon ... il faut faire avec !...
Citation:
Envoyé par
Matt_Houston
J'utilise personnellement MSYS2 sous Windows 7 dans un cadre professionnel depuis plusieurs années ; je veux volontiers croire que ça ne fonctionne pas chez toi mais n'en fait pas une généralité.
Je n'ai jamais dit que le système ne fonctionne pas chez moi car je pense que c'est la plupart du temps un problème de configuration. Je n'en ai donc jamais fait une généralité.
Citation:
Envoyé par
Matt_Houston
- exécution de l'installeur 64-bit récupéré depuis msys2.org ;
- pacman -Syy afin de forcer la mise à jour de la base de données ;
- pacman -Syuu autant de fois que nécessaire (i.e. : deux fois, maximum trois) afin de mettre à jour l'intégralité du système. Il faut fermer le terminal après la première mise à jour, celle des core packages ;
- pacman -Ss gcc pour rechercher le nom du paquet qui nous intéresse, ici la toolchain GCC 64-bit ;
- pacman -S mingw-w64-x86_64-gcc pour l'installer.
Bien sûr que si, j'ai lancé les commandes que vous m'indiquez et comme spécifiées dans une doc
La commande "pacman -Ss gcc" m'avait sortie une palanquée de propositions. Je n'ai pas su choisir la bonne. J'ai donc saisi la commande "pacman -S gcc" pensant qu'elle allait m'installer la version appropriée à mon système. En fait, elle a installé
le paquet "mingw-w64-i686-gcc 7.3.0-1" au lieu du paquet "mingw-w64-x86_64-gcc 7.3.0-2"
ce que la commande aurait dû faire, je pense, puisque le MSYS2 installé est 64bits !...
Citation:
Envoyé par
Matt_Houston
Essaie ensuite de compiler un hello world afin de déterminer si tout est ok.
Je n'ai pas eu besoin du "Hello World" pour vérifier que, sitôt installé, gcc a compilé mon programme pour détecter un problème avec les curses où je me retrouve avec plusieurs versions installées pour trouver la bonne :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| Lou_Papet_2@PC_de_Lou_Papet MINGW64 ~
$ pacman -Ss curses
pacman -Ss curses
mingw32/mingw-w64-i686-ncurses 6.1.20180407-1
System V Release 4.0 curses emulation library (mingw-w64)
mingw32/mingw-w64-i686-pdcurses 3.6-2
Public Domain Curses wincon port (mingw-w64)
mingw64/mingw-w64-x86_64-ncurses 6.1.20180407-1 [installé] <<<==*OK*==
System V Release 4.0 curses emulation library (mingw-w64)
mingw64/mingw-w64-x86_64-pdcurses 3.6-2
Public Domain Curses wincon port (mingw-w64)
msys/cgdb 0.7.0-1
Curses-based interface to the GNU Debugger
msys/hexcurse 1.60.0-1
Versatile ncurses-based hex editor.
msys/ncurses 6.1.20180217-1 (base) [installé]
System V Release 4.0 curses emulation library
msys/ncurses-devel 6.1.20180217-1 (development) [installé]
NCURSES headers and libraries
msys/vifm 0.9.1-1
Ncurses based file manager with vi like keybindings
Lou_Papet_2@PC_de_Lou_Papet MINGW64 ~ |
Citation:
Envoyé par
Matt_Houston
Je te trouve un peu gonflé de vilipender pacman alors que ta stratégie de gestion de paquets revenait jusqu'ici à.. glâner des fichiers au petit bonheur sur le net. :mrgreen:
Une courtoisie en valant une autre, comme vous, je vous trouve un peu gonflé de considérer qu'un utilisateur qui se met à installer un produit et qui a passé pas mal de temps à lire la doc durant ses trous de liberté soit aussi affuté que vous après moultes années d'expérience.
Je ne vilipende rien du tout. Je ne mets pas en cause le programme "Pacman" qui est un programme d'installation basique mais les développeurs qui auraient dû consacrer du temps à proposer un pacman interactif décrivant sommairement mais efficacement les produits comme le font le MinGW Installer et le Synaptics de Linux. Il faut bien voir que le temps supplémentaire considéré par les quelques développeurs comme du temps perdu est autrement largement compensé par la non perte de temps de milliers d'utilisateurs.
Par ailleurs, si un système 64bits est installé, il est absolument inutile d'installer par défaut, je dis bien par défaut, des produits 32bits et vise versa, ne serait-ce que pour l'homogénéité.
Utiliser Pacman dans l'état me ramène avant les années 90 où les installations se faisaient en lignes de commandes comme je les ai connues et qui étaient pénibles. Pour expliquer mon propos, ce qui suit
Code:
1 2 3 4 5 6 7
| Lou_Papet_2@PC_de_Lou_Papet MINGW64 ~
$ pacman
pacman
erreur : aucune opération spécifiée (utiliser -h pour laide)
Lou_Papet_2@PC_de_Lou_Papet MINGW64 ~
$ |
m'apparait comme une erreur de design car, si lancer la commande "Capman" seule passait en "prompting mode", il aurait été assez aisé pour un développeur chevronné de produire un programme interactif en encapsulant la commande "Capman" comme le font "ddd", "xdbx", "cgdb" qui proposent un "gdb" interactif solution à mes yeux plus moderne bien qu'ancienne !...
Pour conclure, je vous remercie infiniment de m'avoir accordé un peu votre temps à m'aider. Je vous en suis très reconnaissant. J'ai pu avancer et puis, à mon âge, je n'ai peut-être plus la même vivacité intellectuelle que celle de quelqu'un de plus de vingt ans mon cadet !...
Bien cordialement et encore merci.
Lou Papet