IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Paramètres de fonction


Sujet :

C

  1. #1
    Futur Membre du Club
    Homme Profil pro
    autre
    Inscrit en
    Juillet 2020
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : autre

    Informations forums :
    Inscription : Juillet 2020
    Messages : 14
    Points : 6
    Points
    6
    Par défaut Paramètres de fonction
    Bonjour à tous,
    Je souhaiterais créer une fonction avec un nombre variable d'argument, sans utiliser la bibliothèque stdarg. D'après les recherches que j'ai effectuées, il suffirait de récupérer l'adresse de la première variable passée en argument, puis augmenter la valeur du pointeur sur ce paramètre de la taille des paramètres passés en arguments. Donc en gros, faire ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    #include <stdio.h>
     
    void f (int n, ...)
    {       //En partant du principe que n indique le nombre de paramètre passés en arguments
    	int *liste = &n+sizeof(int);
    	for(int i = 0; i<n; i++)
    	{
    		liste+=1;  //On récupère l'adresse de l'argument suivant
    		char carAct = *((char*) liste);
    		putchar(carAct);  //On affiche l'argument
    	}
    	putchar('\n');
    }
     
    int main (void)
    {
       f ((int)4, 'a', 'b', 'c', 'z');
       f ((int)7, 'x', 'v', 'a', 'm', 'e', 'a');
     
       return 0;
    }
    Et donc là, je devrais avoir en retour :
    abcz
    xvamea
    Alors qu'en fait, j'obtient ça :
    �a
    xva

    En modifiant le code de cette manière :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #include <stdio.h>
     
    void f (int n, ...)
    {       //En partant du principe que n indique le nombre de paramètre passés en arguments
    	int *liste = &n+sizeof(int);
    	for(int i = 0; i<n; i++)
    	{
    		liste+=1;  //On récupère l'adresse de l'argument suivant
    		char carAct = *((char*) liste);
    		printf("%i ", carAct);  //On affiche l'argument
    	}
    	putchar('\n');
    }
     
    int main (void)
    {
       f ((int)4, 'a', 'b', 'c', 'z');
       f ((int)7, 'x', 'v', 'a', 'm', 'e', 'a');
     
       return 0;
    }
    J'obtient :
    -1 0 97 0
    0 4 120 0 118 0 97

    Ce qui me semble malgrès tout assez étonnant...
    Notez qu'au final, si je remplace par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    void f (int n, ...)
    {       //En partant du principe que n indique le nombre de paramètre passés en arguments
    	int *liste = &n+sizeof(int)+1;
    	for(int i = 0; i<n; i++)
    	{
    		liste+=2;  //On récupère l'adresse de l'argument suivant
    		char carAct = *((char*) liste);
    		printf("%i ", carAct);  //On affiche l'argument
    	}
    	putchar('\n');
    }
     
    int main (void)
    {
       f ((int)4, 'a', 'b', 'c', 'z');
       f ((int)7, 'x', 'v', 'a', 'm', 'e', 'a');
     
       return 0;
    }
    Tout marche correctement tant que je ne dépasse pas les 5 arguments optionnels (donc la deuxième ne marche pas), et ce, quel que soit la taille des paramètres optionnels (à la légère différence qu'avec les long, il faut remplacer le sizeof int de la ligne 3 par sizeof long).
    Et c'est d'ailleurs ce qui me chiffonne surtout :
    Comment, peut on récupérer les valeurs d'adresses séparées de deux octets, alors que celles-ci en font 4 ou 8 (int ou long sur mon pc 64 bits)
    Donc si vous avez des idées sur ce qui cloche, je suis preneur. Merci !
    NB : le + 5 sert à compenser le fait que je crée des variables locales. Si il y avait 3 pointeurs locaux, j'aurais mis 13 (3*4+1).

  2. #2
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Déjà petite erreur sur ton premier code, ce n'est pas "7" mais "6" (enfin si j'ai bien compris vu qu'il n'y a que 6 arguments). Enfin bon c'est pas ça qui empèche de trouver. Accessoirement le cast nuit plus qu'il n'aide (si tu ne le mets pas, il y a alors cast implicite par rapport au paramètre "n" de la fonction). Et quand on essaye de faire ce genre de tests, on évite au maximum tout ce qui peut-être flou comme la taille d'un int en essayant de forcer au maximum avec "short" ou "long".
    Ce qui m'amène d'ailleurs à une seconde remarque: si je remplace "int n" par "unsigned int n" ça "marchotte" encore (je veux dire que ça donne comme toi) mais si je mets "unsigned short" ou "unsigned long" là ça ne marche plus du tout. Ce qui laisse penser que ta règle "il suffirait de récupérer l'adresse de la première variable passée en argument, puis augmenter la valeur du pointeur sur ce paramètre de la taille des paramètres passés en arguments" n'est pas si vraie que ça.

    De là, moi je me suis demandé "y a-t-il vraiment une règle qui permette de trouver les emplacements de ces arguments ?"

    J'ai donc tapé le code suivant...
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #include <stdio.h>
     
    void f (unsigned long n, ...)
    {       //En partant du principe que n indique le nombre de paramètre passés en arguments
    	char *liste = (char*)&n;
    	char but[]="abc";
    	unsigned long cpt;
    	printf("liste=%p\n", liste);
    	for (cpt=0; cpt < 16*n && *liste != 'z' ; cpt++, liste++) {
    		char *pt;
    		for (pt=but; *pt != '\0'; pt++)
    			if (*liste == *pt) printf("liste=%p (%c), diff=%lu(%lu)\n", liste, *liste, liste-(char*)&n, cpt);
    	}
    	putchar('\n');
    }
     
    int main (void)
    {
       f (4, 'a', 'b', 'c', 'z');
       f (7, 'a', 'b', 'c', 'a', 'b', 'c', 'z');
     
       return 0;
    }

    Et le résultat
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    liste=0x7ffdabc081f8
    liste=0x7ffdabc08204 (a), diff=12(12)
    liste=0x7ffdabc08205 (b), diff=13(13)
    liste=0x7ffdabc08206 (c), diff=14(14)
    liste=0x7ffdabc08228 (a), diff=48(48)
    liste=0x7ffdabc08230 (b), diff=56(56)
     
    liste=0x7ffdabc081e8
    liste=0x7ffdabc081f4 (a), diff=12(12)
    liste=0x7ffdabc081f5 (b), diff=13(13)
    liste=0x7ffdabc081f6 (c), diff=14(14)
    liste=0x7ffdabc08218 (a), diff=48(48)
    liste=0x7ffdabc08220 (b), diff=56(56)
    liste=0x7ffdabc08228 (c), diff=64(64)
    liste=0x7ffdabc08230 (a), diff=72(72)
    liste=0x7ffdabc08238 (b), diff=80(80)
    Là un premier constat: au second appel, il aurait dû trouver un second cycle "abc" immédiatement après le premier et non pas 32 cases plus loin.

    Ensuite, je remplace char but[]="abc" par char *but="abc" (le tableau devient l'adresse d'une chaine statique dans le tas). A priori cela ne devrait rien changer. En fait j'ai en réalité tapé ça par habitude d'économiser quand je peux, ne pensant pas que cela ferait une différence. Toutefois cela en a fait une
    Le résultat
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    liste=0x7ffc6daaf788
    liste=0x7ffc6daaf7b8 (a), diff=48(48)
    liste=0x7ffc6daaf7c0 (b), diff=56(56)
     
    liste=0x7ffc6daaf778
    liste=0x7ffc6daaf7a8 (a), diff=48(48)
    liste=0x7ffc6daaf7b0 (b), diff=56(56)
    liste=0x7ffc6daaf7b8 (c), diff=64(64)
    liste=0x7ffc6daaf7c0 (a), diff=72(72)
    liste=0x7ffc6daaf7c8 (b), diff=80(80)
    Donc là, il ne trouve plus du tout le 'c' du premier appel, ni le second 'c' du second appel. En fait, j'ai l'impression que le "abc" qu'il trouve en positions 48, 56 et 64 sont le "abc" de mon "but".

    Maintenant je remplace unsigned long n par unsigned short n et pareil pour cpt (le "but" est resté "char*"). Le résultat
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    liste=0x7ffdce5735bc
    liste=0x7ffdce5735e8 (a), diff=44(44)
    liste=0x7ffdce5735f0 (b), diff=52(52)
    liste=0x7ffdce5735f8 (c), diff=60(60)
     
    liste=0x7ffdce5735ac
    liste=0x7ffdce5735d8 (a), diff=44(44)
    liste=0x7ffdce5735e0 (b), diff=52(52)
    liste=0x7ffdce5735e8 (c), diff=60(60)
    liste=0x7ffdce5735f0 (a), diff=68(68)
    liste=0x7ffdce5735f8 (b), diff=76(76)
    Ensuite je compile (j'ai oublié de dire que je suis avec gcc 8.3) avec l'option "-O2" qui est une demande d'optimisation. Et le résultat
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    liste=0x7ffcc770e86c
     
    liste=0x7ffcc770e85c
    liste=0x7ffcc770e8a0 (c), diff=68(68)
    Donc voilà. Tout ceci pour dire qu'il y a tant de paramètres qui jouent (état de la pile entre autre), qu'on peut difficilement en tirer une conclusion aussi simple que "adresse du premier argument puis décalage de l'âge de ma grand-mère". Surtout que rien ne dit que le décalage ne se fait pas vers l'arrière

    Citation Envoyé par ViveLasm Voir le message
    sans utiliser la bibliothèque stdarg
    Quelque chose me dit que si quelqu'un s'est fait ch... à la développer, ce n'était pas pour rien
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Futur Membre du Club
    Homme Profil pro
    autre
    Inscrit en
    Juillet 2020
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : autre

    Informations forums :
    Inscription : Juillet 2020
    Messages : 14
    Points : 6
    Points
    6
    Par défaut
    Cc,
    Merci de ta réponse.
    Bon, j'ai un peu chercher sur comment faire, et en regardant la structure des fonctions traditionnelles, j'en suis arrivé à ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
     
    #include <stdio.h>
     
     //Fonction pour afficher 5 long, puis un nombre indéterminé de caractères
     /*Attention : ne fonctionne pas avec optimisation : trop de modification dans la structure du programme (et surtout des fonctions à nombre
     variable de paramètres) : manifestement, aucune sur les grosses fonctions à nombre invariable d'arguments*/
    void f (int n, ...)
    {       //En partant du principe que n indique le nombre de paramètre passés en arguments
    		/*Le passage d'argument se fait de la même manière que si l'on utilise des int (5 arguments suivent le premier, puis l'on saute pour
    		accéder aux suivants). De plus, il faut incrémenter liste à chaque fois de 2, et d'abord incrémenter l'adresse de liste de 9 (deux int 
    		pour liste, 7 pour la sauvegarde de la pile, enfin je suppose)*/
    		/*Plus explicitement, le saut d'adresse se fait par tranches de 4 : liste+1 => liste+4. Ensuite, passé les 5 premiers arguments, il faut 
    		faire un saut de 36 (je ne sais pas pour quoi) pour récupérer les arguments suivants. Ensuite, continuer à sauter de 2 en 2. Enfin, si
    		l'on met des arguments suplémentaires dans la fonction, il faut incrémenter liste (lors du premier saut et du deuxième) de la taille
    		de ces arguments. Exemple : 2 int* = 4 int => liste+4*/
    	int* RSP;
    	int* RBP;
    	asm("mov %%rbp, %%rbx"
    	:"=b" (RBP));
    	asm("mov %%rsp, %%rax"
    	:"=a" (RSP));
    	printf("%p\n", RBP);
    	printf("%p\n", RSP);
    	// NB : RSP : pointeur de pile, RBP : pointeur de base de la pile => Utile pour le debug
    	int *liste = &n+9+4;
    	for(int i = 0; i<n && i<5; i++)
    	{
    		liste+=2;  //On récupère l'adresse de l'argument suivant
    		long carAct = *((long*) liste);
    		printf("%li ", carAct);  //On affiche l'argument
    	}
    	liste+=40;
    	for(int i = 5; i<n; i++)
    	{
    		liste+=2;
    		char carAct = *((char*) liste);
    		printf("%c ", carAct);  //On affiche l'argument
    	}
    	putchar('\n');
    }
     
    int main (void)
    {
    	f ((int)7, 'a', 'b', 'c', 'z', 'a', 'a', 'b');
    	f ((int)7, 123456, 123456, 123456, 123456, 123456, 'c', 'z');
     
       return 0;
    }
    Ça marche bien tant qu'il n'y a pas d'optimisation. Je n'ai pas réussi à changer le code en cas d'optimisation, car la structure des fonctions traditionnelles ne changent pas... (sauf que le sp n’existe plus). Ensuite, je suis d'accord sur le fait que les bibliothèques ne sont pas là pour rien, mais il y a des fois où tu es contraint de t'en passer (Programmation d'os, embarqué...).
    Ensuite, normalement, il y a des normes entourant le passage d'argument aux fonctions en C. Mais malheureusement je n'ai rien trouvé dessus... Donc si tu as un peu de doc à me proposer je suis partant

  4. #4
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par ViveLasm Voir le message
    Ensuite, je suis d'accord sur le fait que les bibliothèques ne sont pas là pour rien, mais il y a des fois où tu es contraint de t'en passer (Programmation d'os, embarqué...).
    Moui, effectivement je suis d'accord, aucune situation n'est pareille à une autre. Mais dans ce cas, peut-être alors essayer de rester dans les classiques (fonction standard, nb de paramètres connus, etc)
    Ou alors utiliser le système argc/argv. Ta fonction recevant alors un tableau et le nb de ses éléments. M'est avis que ça restera toujours plus sain que ce... clafoutis

    Citation Envoyé par ViveLasm Voir le message
    Donc si tu as un peu de doc à me proposer je suis partant
    Désolé si j'avais eu je t'aurais donné.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Citation Envoyé par ViveLasm Voir le message
    Ensuite, normalement, il y a des normes entourant le passage d'argument aux fonctions en C. Mais malheureusement je n'ai rien trouvé dessus... Donc si tu as un peu de doc à me proposer je suis partant
    x86 calling conventions, lien wiki en anglais

  6. #6
    Futur Membre du Club
    Homme Profil pro
    autre
    Inscrit en
    Juillet 2020
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : autre

    Informations forums :
    Inscription : Juillet 2020
    Messages : 14
    Points : 6
    Points
    6
    Par défaut
    Ok merci beaucoup à tout les deux !

  7. #7
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    17 451
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 17 451
    Points : 43 097
    Points
    43 097
    Par défaut
    Je souhaiterais créer une fonction avec un nombre variable d'argument
    Il faut que tu regardes du coté des fonctions variadiques, comme printf.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  8. #8
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par chrtophe Voir le message
    Il faut que tu regardes du coté des fonctions variadiques, comme printf.
    Ben il me semble que ces fonctions utilisent stdarg, et c'est un truc que le PO ne peut pas utiliser...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  9. #9
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    17 451
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 17 451
    Points : 43 097
    Points
    43 097
    Par défaut
    ah oui ok.

    Désolé, je suis pas spécialiste C.
    on peut utiliser une notation void f (int n, ...) sans stdarg ?

    Ca me parait pas simple, on ne connait pas le type de l'argument, donc la taille de l'argument à dépiler, et si c'est un pointeur ou non.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  10. #10
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par chrtophe Voir le message
    on peut utiliser une notation void f (int n, ...) sans stdarg ?
    Ben... c'était en fait la question de départ
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  11. #11
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    17 451
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 17 451
    Points : 43 097
    Points
    43 097
    Par défaut
    Je me suis mal exprimé, je voulais savoir si on pouvait compiler le code avec ... sans stdarg.h
    Du coup j'ai testé et oui avec l'option -Wall sans erreur.

    Par contre, en C je vois pas comment récupérer les arguments après le 1er sans les fonctions va_*
    Il faudrait tester avec le code asm comment est terminée la liste des arguments. Peut-être avec un pointeur NULL.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  12. #12
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Citation Envoyé par chrtophe Voir le message
    Par contre, en C je vois pas comment récupérer les arguments après le 1er sans les fonctions va_*
    C'est simple c'est le lien que j'ai posté les conventions d'appels (<- on m'a repris sur le terme en français )

    L'idée c'est de prendre le pointeur du premier argument (le pointeur doit pointer sur la pile) et ensuite en incrémentant le pointeur tu peux prendre 1 à 1 les arguments passés en paramètres et ensuite 1 à 1 les variables locales.

    Le problème : c'est qu'il y a plusieurs conventions d'appels (quoique avec le passage du x64 et 1 coup de balai, il y en reste que 3 ou 4 il me semble). Parce que
    • Les arguments peuvent être empilés de gauche à droite ou de droite à gauche
    • L'adresse de retour est aussi empilée : avant ou après les arguments
    • Les arguments peuvent être empilés mais également mis dans des registres (__fastcall), en mémoire, ...

    Donc, il faut forcer la convention d'appel qui va bien, virer toutes les optimisations et vérifier dans l'assembleur qu'on empile les arguments

    stdarg.h est le seul code officiel qui parse les arguments - tout le reste c'est du bricolo-bricolette

    Le mieux à faire :
    • passer 1 tableau avec les valeurs. Le hic, dans le tableau, tous les arguments doivent avoir le même type
    • passer 1 tableau générique avec les valeurs. Et/ ou utiliser massivement des unions.
    • Utiliser le C++, avec la spécialisation des templates et la surcharge. Mais pareil, si les arguments peuvent avoir plein de types cela va faire 1 tonne de code
    • Utiliser le C++ et 1 container STL qui va bien

  13. #13
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Si l'on part en C++, les variadic templates sont faits pour ça et remplissent parfaitement ce rôle.
    En C pur, est-ce que les variables d'appel seront bien toujours accessibles avec une incrémentation de pointeur ? Est-ce qu'il peut y avoir des cas où les valeurs sont mises dans différents registres etc qui sortent de ce cas et où leur accès serait différent ?
    Sinon, on pourrait bidouiller avec des macros et utiliser les var args, pas sûr que ce soit plus simple par contre..
    Un mix où les paramètres sont passés dans un {}, p-e de void*, pourrait rendre cela plus aisé ?
    Enfin, pour quelle raison tordue injustifiable voudrait-on ne pas utiliser stdargs ?
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  14. #14
    Futur Membre du Club
    Homme Profil pro
    autre
    Inscrit en
    Juillet 2020
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : autre

    Informations forums :
    Inscription : Juillet 2020
    Messages : 14
    Points : 6
    Points
    6
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Enfin, pour quelle raison tordue injustifiable voudrait-on ne pas utiliser stdargs ?
    La réponse est dans la discussion Sinon, j'aime bien le bricolage Mais il faudrait des lib utilisable partout (sans OS). Je ne sais pas si c'est le cas de starg. Quelqu'un sait ?

  15. #15
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    stdarg fait partie du standard.
    À moins que tu comptes aussi créer un compilateur, il n'y a aucune raison de ne pas l'utiliser.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

Discussions similaires

  1. Réponses: 10
    Dernier message: 04/01/2006, 16h57
  2. liste énumérée de const. perso comme paramètre de fonction
    Par batou22003 dans le forum VB 6 et antérieur
    Réponses: 8
    Dernier message: 13/12/2005, 20h37
  3. Paramètres de fonction : pointeurs ou valeurs ?
    Par Xandar dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 30/11/2005, 16h50
  4. Retrouver les valeurs des paramètres des fonctions d'une DLL
    Par Bernard Martineau dans le forum Langage
    Réponses: 6
    Dernier message: 08/11/2005, 10h42
  5. Paramètre de fonction
    Par Reynald dans le forum Débuter
    Réponses: 6
    Dernier message: 05/01/2005, 21h48

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo