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 :

Structure d'un programme d'émulation


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre très actif

    Homme Profil pro
    Développeur Web
    Inscrit en
    Octobre 2013
    Messages
    200
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Pérou

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Octobre 2013
    Messages : 200
    Par défaut Structure d'un programme d'émulation
    Je cherche à ce que ça exécute viiiiite !

    Une bonne technique pour accélérer l'exécution d'un code écrit en C, pourrait résider dans les faits :
    - d’éviter d'utiliser les switchs. En fait, je ne sais pas comment est implémenté un switch, mais je ne vois pas comment faire sans une (+ ou - longue) série de "if else if"
    - d'éviter le passage de paramètre aux fonctions.
    Ceci oblige a utiliser des viables globales, ou une structure pointée par une globale.

    J'ai écrit un émulateur. Il reçoit en entrée des codes compris en 0 et 256. Le logiciel actuel comporte près de 300 fonctions. Pour régler le problème des switchs, j'ai utilisé intensivement les tableaux de pointeurs sur fonctions, et c'est la variable qui est entre parenthèse dans :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    switch (variable) { ... }
    qui sert d'index dans ce tableau. Chaque fois qu'on déclare une variable locale à une fonction (dite automatique), il faut réserver de la place dans la pile, ce qui est probablement ridicule en terme de temps d'exécution. J'ai réglé le problème de la façon suivante :

    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
      // inclusion de headers, déclaration des types de structures, 
      // fonction etc : équivalent à un ".h"
      // Le code C de l'émulateur ne comporte qu'une fonction visible :
    void make_a_step (void) {
      register MyStruct_t *GlobStruct;  // Notez le modificateur "register"
      int local1, local2, etc...
      static void (*functTable[4])();   // "static" modificateur obligatoire
     
      void funct1 (void) { ... }
      void funct2 (void) { ... }
      void funct3 (void) { ... }
      void funct4 (void) { ... }
     
      void init (void) {
        functTable[0] = funct1; // Ce n'est pas écrit ainsi,
        functTable[1] = funct2; // ça revient au même.
        functTable[2] = funct3;
        functTable[3] = funct4;
      }
     
      // le corps de la fonction "make_a_step" commence ici...
      if (GlobStruct->_flagInited) {
       init();
       GlobStruct->_flagInited = 1;
      }
      ...
      ...
     
     
    } // Fin de make_a_step()
    La liste de ce bout de code est extrêmement simplifié, puisque le code actuel comporte plus de 3000 lignes.

    Pour pouvoir mettre au point cet émulateur, il m'aura fallu écrire un moniteur (environs mille lignes). Je peut ainsi "programmer l'émulation en saisissant des codes que je fait exécuter en pas à pas, tout ceci grâce au moniteur. Ce moniteur est supposé permettre l'éxécution de code en pas à pas, ainsi que l'exécution d'une liste de codes en continu. Évidemment, la mise au point du code c'est fait en mode "pas à pas". Mais fait étrange, le programme se plante quand je passe de "pas à pas" en "run", OU quand je passe de "run" en "pas à pas". Nemiver (la "belle et vielle promesse non tenue") ou gdb n'y ont rien fait : je ne vois qu'une perte de contexte mais sans pouvoir corriger en gardant la structuration actuelle décrite plus haut.

    J'ai essayé sans succès :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void make_a_step (register MyStruct_t *GlobStruct) {
      int local1, local2, etc...
      static void (*functTable[4])();   // Static obligatoire
      ...
    }
    La mémoire affectée à la variable pointée par GlobStruct l'a été par.le monitor, avec malloc. Il est peut probable (impossible) qu'elle soit déplacée dans la mémoire par le système.

    Finalement, ça fonctionne,ainsi, avec un minimum de modif de la source, mais c'est philosophiquement insatisfaisant :

    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
      MyStruct_t *GlobStruct;       // Notez le modificateur "register"
      int local1, local2, etc...    // Elles ne sont plus locales (mal nommées!
      void (*functTable[4])();      // Static PLUS obligatoire, puisque globale !
     
      void funct1 (void) { ... }
     
      ...
     
        functTable[3] = funct4;
      }
     
    void make_a_step (void) {
      if (GlobStruct->_flagInited) {
       init();
       GlobStruct->_flagInited = 1;
      }
      ...
      ...
     
     
    } // Fin de make_a_step()
    Quelqu'un pourrait-il me dire pourquoi Linux perd les pédales ? Je pense que les programmeurs réguliers de threads pourraient sentir l'origine du problème et ainsi pouvoir m'indiquer comment le résoudre...

    J'aurais préféré la première forme de structure décrire plus haut. J'ai bien vu que le logiciel perd vraiment les pédales entre "run" et "faire un pas" sans comprendre pourquoi. Je suppose que le code (la fonction make_a_step() complète) n'est pas "déplacé" par le système, à quelque occasion, auquel cas la fonction init serait à relancer ? J'ai vérifier en écrivant ceci :

    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
      // inclusion de headers, déclaration des types de structures, 
      // fonction etc : équivalent à un ".h"
      // Le code C de l'émulateur ne comporte qu'une function visible :
      void *gFuncPosRef = NULL;
     
    void make_a_step (void) {
      register MyStruct_t *GlobStruct;  // Modificateur "register"
      int local1, local2, etc...
      static void (*functTable[4])();   // "static" obligatoire
     
      void funct1 (void) { ... }
     
      ...
     
        functTable[3] = funct4;
      }
     
      // le corps de la fonction "make_a_step" commence ici...
      if (!gFuncPosRef || gFuncPosRef!= &make_a_step) {
       init();
       gFuncPosRef = &make_a_step;
      }
      ...
      ...
     
     
    } // Fin de make_a_step()
    Mais ça marche pas.

    EDIT :
    Mais j'y pense : peut-être qu'écrire cette "fonction" comme étant une librairie résoudrait mon problème ?

  2. #2
    Expert confirmé
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    Mai 2010
    Messages
    3 226
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : Mai 2010
    Messages : 3 226
    Par défaut
    Citation Envoyé par Paul_Le_Heros Voir le message
    Je cherche à ce que ça exécute viiiiite !

    Une bonne technique pour accélérer l'exécution d'un code écrit en C, pourrait résider dans les faits :
    - d’éviter d'utiliser les switchs. En fait, je ne sais pas comment est implémenté un switch, mais je ne vois pas comment faire sans une (+ ou - longue) série de "if else if"
    - d'éviter le passage de paramètre aux fonctions.
    Ceci oblige a utiliser des viables globales, ou une structure pointée par une globale.
    Alors non c'est faux , aucun rapport entre le switch et les variables globales (encore heureux qu'on peut faire un switch sans variable global).
    Bref tout dépend de ce que tu veux émuler , si tu veux émuler une machine avec une dizaine de Mhz , alors le switch marche sans soucis , et ça marchais sans soucis sur mon ancien Pentium 3 qui émuler facilement une SNES
    (On peut prendre l’exemple d'un RasPi qui émule en software tout les consoles 8/16 bits et les anciennes borne d'arcade aussi).
    Par info MAME émule quasiment tout en software (avec if etc etc) de ce que j'ai pu remarquer.
    Si par exemple on prend une Neo Geo qui est une machine assez puissante pour l'époque (12 Mhz) , elle ne fournissait que 2,4 MIPS (millions d'instructions par seconde) , ce qui devrait posait aucun souci à émuler sur un ordi moderne :p
    Cela dépend si tes instructions sont facile à décodé ,certain type de proc le sont plus facilement que d'autre.

    Pour les machines un peu plus puissante (donc si on prend comme les consoles un peu plus puissante comme la dreamcast / PS2/ Gamecube et autre) , on fait du JIT donc de la compilation à la volée.

  3. #3
    Membre très actif

    Homme Profil pro
    Développeur Web
    Inscrit en
    Octobre 2013
    Messages
    200
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Pérou

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Octobre 2013
    Messages : 200
    Par défaut
    Bonjour et merci Kannagi, pour votre réponse.
    Citation Envoyé par Kannagi Voir le message
    Alors non c'est faux , aucun rapport entre le switch et les variables globales (encore heureux qu'on peut faire un switch sans variable global).
    Je sais ça, bien sûr.

    Je crois que j'aurais dû écrire (premier listing de code, ligne 5):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    register MyStruct_t *GlobStruct = gGlobStruct; // Un registre pointe toute les infos de l'émulateur.
    Ce qui permets à toutes les autres fonctions qui se trouve entre cette ligne 5 et le corps de fonction "make_a_step", ligne 22, de disposer d'un accès aux infos sans :
    1. ou recevoir un paramètre pointant sur ces infos, genre
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      void fonctTruc (MyStruct_t *sPtr) { ... }
    2. ou créer une variable locale initialisée de sorte à pointer sur ces infos, genre
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      void fonctTruc (void) { lMyStruct_t *lSPtr = gGlobStruct; ... }
    Ces deux possibilités ne consomment certainement pas beaucoup de code (donc de temps), mais certainement plus qu'un registre pointant cette structure et disponible pour toutes les fonctions "internes" ou "privées" de make_a_step().

    Une lecture très attentive de ces pseudos "listings" est nécessaire pour la compréhension du problème...

  4. #4
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 811
    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 811
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Paul_Le_Heros Voir le message
    Je cherche à ce que ça exécute viiiiite !
    Bonjour à toi aussi

    Citation Envoyé par Paul_Le_Heros Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void make_a_step (void) {
    	static void (*functTable[4])();   // "static" modificateur obligatoire
    	...
    	void init (void) {
    		functTable[0] = funct1; // Ce n'est pas écrit ainsi,
    		functTable[1] = funct2; // ça revient au même.
    		functTable[2] = funct3;
    		functTable[3] = funct4;
    	}
    	...
    } // Fin de make_a_step()
    La liste de ce bout de code est extrêmement simplifié, puisque le code actuel comporte plus de 3000 lignes.
    Moi j'aurais plutôt écrit ça ainsi: static void (*functTable[4])()={funct1, funct2, funct3, funct4}. Mais surtout, comment "init()" peut connaitre le tableau "funcTable" ? Et plus généralement, on a le droit, en C, de définir une fonction dans une fonction ???

    Citation Envoyé par Paul_Le_Heros Voir le message
    Mais j'y pense : peut-être qu'écrire cette "fonction" comme étant une librairie résoudrait mon problème ?
    Une librairie possède un index qui optimise les appels. Donc effectivement ça peut améliorer les accès...
    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
    Membre très actif

    Homme Profil pro
    Développeur Web
    Inscrit en
    Octobre 2013
    Messages
    200
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Pérou

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Octobre 2013
    Messages : 200
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Moi j'aurais plutôt écrit ça ainsi: static void (*functTable[4])()={funct1, funct2, funct3, funct4}. Mais surtout, comment "init()" peut connaitre le tableau "funcTable" ?
    Je suis surpris par la question : la déclaration est faite ligne 2 ! Mais vous avez pré-sentez le problème : le compilateur ne peut pas générer le code d'initialisation du tableau tel que vous l'avez écrit...

    Citation Envoyé par Sve@r Voir le message
    Et plus généralement, on a le droit, en C, de définir une fonction dans une fonction ???
    Probablement oui, puisque cela a fonctionné. Je vous invite à écrire un bout de code pour vérifier.

    Il se passe quelque chose à un moment qui fait que les tableaux ne pointent plus ce qu'il devraient et l'on fait après exécution de la fonction d'initialisation. C'est certainement très intime : je ne comprends pas pourquoi, donc encore plus difficile de remédier.

    Citation Envoyé par Sve@r Voir le message
    Une librairie possède un index qui optimise les appels. Donc effectivement ça peut améliorer les accès...
    Pour l'instant je garde la situation actuelle, mais j'essayerai.

  6. #6
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par Paul_Le_Heros Voir le message
    Probablement oui, puisque cela a fonctionné. Je vous invite à écrire un bout de code pour vérifier.
    Non, les fonctions imbriquées ne sont pas permises en C standard (sauf à avoir changer récemment). Mais c'est proposé comme extension par certains compilateurs dont gcc.

    Citation Envoyé par Paul_Le_Heros Voir le message
    Il se passe quelque chose à un moment qui fait que les tableaux ne pointent plus ce qu'il devraient et l'on fait après exécution de la fonction d'initialisation. C'est certainement très intime : je ne comprends pas pourquoi, donc encore plus difficile de remédier.
    Sans un code minimal qui reproduit le problème c'est difficile de voir ce qui peut se passer.
    Pour ce genre de problème, les outils classiques : compilation avec tous les warning activés (et en les corrigeant) sur différents compilateurs, analyse statique, exécution sous valgrind ou outils du même type, exécution sous debugger.


    Quelques remarques : le register est probablement inutile, l'utilisation de globales ne devrait pas te faire gagner grand chose, l'élimination des switch guère plus, les manipulations mémoires que tu fais sont compliquées (et potentiellement source d'erreur) pour pas grand chose.
    Je doute que la méthode soit bonne. Avant d'utiliser des constructions tordues pour gagner en perf, fais un code simple qui fonctionne et mesure. Ensuite, si besoin, tu peux introduire des constructions plus tordues et mesurer si tu gagnes effectivement (il faut toujours mesurer, les a priori sur les performances sont généralement assez mauvais et on est régulièrement surpris de ce qu'arrive à faire le compilateur).
    Ah, et pour, penses à compiler en activant les optimisation (au moins O2, à tester en O3).

  7. #7
    Membre très actif

    Homme Profil pro
    Développeur Web
    Inscrit en
    Octobre 2013
    Messages
    200
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Pérou

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Octobre 2013
    Messages : 200
    Par défaut
    Citation Envoyé par gl Voir le message
    Non, les fonctions imbriquées ne sont pas permises en C standard (sauf à avoir changer récemment). Mais c'est proposé comme extension par certains compilateurs dont gcc.
    Bon, ben je crois que c'est là que ça se passe. Cette extension est disponible en GCC, mais c'est pas finie et/ou stable.

    Citation Envoyé par gl Voir le message
    Sans un code minimal qui reproduit le problème c'est difficile de voir ce qui peut se passer.
    Je ne vais pas essayer parce que les tartines tombant toujours coté beurre, il me faudra des milliers de lignes pour que ça puisse planter et ça plantera pas. Non, pas d'investigation avec cette méthode pour moi.

    Citation Envoyé par gl Voir le message
    Pour ce genre de problème, les outils classiques : compilation avec tous les warning activés (et en les corrigeant) sur différents compilateurs, analyse statique, exécution sous valgrind ou outils du même type, exécution sous debugger.
    Je suis exactement dans ce cahier des charges du développement, et les avertissements convertis en erreurs. pour forcer la correction ! Valgrind est un outil merveilleux ! Mais là : il ne dit pas grand chose d'aidant.

    Citation Envoyé par gl Voir le message
    Quelques remarques : le register est probablement inutile, l'utilisation de globales ne devrait pas te faire gagner grand chose, l'élimination des switch guère plus, les manipulations mémoires que tu fais sont compliquées (et potentiellement source d'erreur) pour pas grand chose.
    Puisque ça tourne, j'ai même constaté que ce dernier code fonctionnel utilisant des globales (tous O0) est plus petit qu'alors que cela plantait ce qui va à l'opposé de l'objectif de cette forme d'écriture. Je n'ai pas essayé d'optimisation par le compilateur, et pour ce qui est de la vitesse d'exécution, je dois encore chercher pourquoi dans une console lambda et sans priorités particulières, le code s'exécute à raison de 10^^6 pas en 2 secondes, alors et le même code sous Némiver vas au moins 10 fois plus vite (évaluation à la louche). Par ailleurs, ces manipulations mémoires ne me satisfont pas non plus, s'il s'agit de ce qui est fait pour initialiser. Par contre, l'utilisation de tableaux de pointeurs sur fonctions pour accélérer le traitement me semble correcte et irréprochable si ce n'est que l'écriture n'étant pas conventionnelle, c'est plus difficile à lire et donc à maintenir, sans bons commentaires.

    Citation Envoyé par gl Voir le message
    Je doute que la méthode soit bonne. Avant d'utiliser des constructions tordues pour gagner en perf, fais un code simple qui fonctionne et mesure. Ensuite, si besoin, tu peux introduire des constructions plus tordues et mesurer si tu gagnes effectivement (il faut toujours mesurer, les a priori sur les performances sont généralement assez mauvais et on est régulièrement surpris de ce qu'arrive à faire le compilateur).
    Les torsions sont conséquences de vouloir un registre pointant la structure disponible pour toutes les fonctions, plutôt que de charger un variable locale (éventuellement dans un registre), à cet effet, pour chaque fonction.

    Citation Envoyé par gl Voir le message
    Ah, et pour, penses à compiler en activant les optimisation (au moins O2, à tester en O3).
    J'étais convaincu que les optimisations n'étaient pas propices au bon déroulement du développement. Je me tromperais donc ? Pourriez-vous m'en dire plus sur ce point ?

    Merci pour ces réponses. Je me demande si je dois marquer ce fil de discutions comme résolu...

  8. #8
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par Paul_Le_Heros Voir le message
    Bon, ben je crois que c'est là que ça se passe. Cette extension est disponible en GCC, mais c'est pas finie et/ou stable.
    A priori si elle fonctionne. Il faut voir si tu es bien dans un cas où tu peux l'utiliser mais normalement il n'y a pas de souci.
    Globalement, quand un code ne fonctionne pas, il est largement plus probable que l'erreur soit dans notre code que dans le compilateur ou la bibliothèque standard (ou dans d'autres bibliothèques largement éprouvées).

    Citation Envoyé par Paul_Le_Heros Voir le message
    Je suis exactement dans ce cahier des charges du développement, et les avertissements convertis en erreurs. pour forcer la correction ! Valgrind est un outil merveilleux ! Mais là : il ne dit pas grand chose d'aidant.
    C'est à dire ? Qu'entends tu par cahier des charges du développement ici, quelles options as tu utiliser ? Quels compilateurs ? Que sort valgrind ? Que dit le debuger ? As-tu mis un point d'arrêt sur le changement de valeur de la variable ?

    Citation Envoyé par Paul_Le_Heros Voir le message
    Par contre, l'utilisation de tableaux de pointeurs sur fonctions pour accélérer le traitement me semble correcte et irréprochable si ce n'est que l'écriture n'étant pas conventionnelle, c'est plus difficile à lire et donc à maintenir, sans bons commentaires.
    Peut-être ! As-tu seulement mesuré si tu gagnais vraiment quelque chose ?

    Citation Envoyé par Paul_Le_Heros Voir le message
    J'étais convaincu que les optimisations n'étaient pas propices au bon déroulement du développement. Je me tromperais donc ? Pourriez-vous m'en dire plus sur ce point ?
    Pour la mise au point et le debug du code, ce n'est pas utile voire nuisible. Mais si tu commences à vouloir optimiser et gagner en vitesse, c'est la première étape (une fois que le code, dans sa forme simple, fonctionne bien sur), et il aura probablement un impact plus important que toutes les tentatives d'optimisation que tu vas faire.

  9. #9
    Membre Expert Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    753
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 753
    Par défaut
    Hello,

    Alors, oui, on a le droit de mettre une fonction dans une fonction (gcc 6.3.0), mais il faut l'appeler.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <stdio.h>
     
    int main(void) {
    	int d=0;
     
    	void setD(void) {
    		d=1;
    	}
     
    	printf("d=%d",d);
     
    	return(0);
    }
    Sortie: d=0
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <stdio.h>
     
    int main(void) {
    	int d=0;
     
    	void setD(void) {
    		d=1;
    	}
    	setD();
    	printf("d=%d",d);
     
    	return(0);
    }
    sortie: d=1

  10. #10
    Membre très actif

    Homme Profil pro
    Développeur Web
    Inscrit en
    Octobre 2013
    Messages
    200
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Pérou

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Octobre 2013
    Messages : 200
    Par défaut
    Merci pour votre post.

    Citation Envoyé par edgarjacobs Voir le message
    Hello,
    Alors, oui, on a le droit de mettre une fonction dans une fonction (gcc 6.3.0), mais il faut l'appeler.
    Il me semble assez logique qu'il faille l'appeler !

    Merci pour cet exemple de code, mais la fonction main() n'est-elle pas un peu "particulière" ? Je proposerais :
    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
    #include <stdio.h>
     
    int gD = 7;
     
    int emu (int step) {
    	void setGdTo0 (void) {
    		gD = 0;
    	}
     
    	void setGdTo1 (void) {
    		gD = 1;
    	}
     
    	void (*SetGdTable[2])(void) = { setGdTo0, setGdTo1 };
    #if 0
    	switch (step) {
    		case 0; SetGdTo0(); break;
    		default : SetGdTo1();
    	}
    #else
    	SetGdTable[step & 1]();
    #endif
    	return 0;
    }
     
    int main(void) {
     
    	printf("d=%d\n",gD);
    	emu(0);
    	printf("d=%d\n",gD);
    	emu(1);
    	printf("d=%d\n",gD);
    	return(0);
    }
    Dont la sortie est :

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [STRUCTURE] Structure d'un programme JAVA
    Par pflany dans le forum Langage
    Réponses: 11
    Dernier message: 18/04/2020, 22h05
  2. Réponses: 18
    Dernier message: 04/06/2007, 00h55
  3. Structure d'un programme
    Par bontempf dans le forum SQL Procédural
    Réponses: 6
    Dernier message: 10/03/2007, 23h48
  4. Apprendre la structure d'un programme en Prolog
    Par minen dans le forum Prolog
    Réponses: 3
    Dernier message: 26/02/2007, 09h48
  5. [debutant] structure d'un programme
    Par poukill dans le forum Débuter
    Réponses: 17
    Dernier message: 19/05/2006, 15h33

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