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 :

Variable, globale ou passage par pointeur ?


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé

    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Février 2012
    Messages
    231
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2012
    Messages : 231
    Par défaut Variable, globale ou passage par pointeur ?
    Bonjour,

    Ma question est :
    Utiliser un pointeur ou une variable globale pour passer une structure à des fonctions.

    Etat de la situation :

    Hardware : Arduino MKR1010 SAMD21 Cortex®-M0+ 32bit low power ARM® MCU
    Utilisateur : 1 l'arduino.
    Programmeur :1 moi.

    Le programme: Lire les valeurs de capteurs et les mettre dans un tableau de valeurs moyennes glissantes minutes.

    Avec un ordinateur "standard", la question ne se poserait que peu, un pointeur évidemment.

    Mais avec Arduino, la séquence est quelque peu différente.

    Un Arduino démarre avec un "setup" qui n'est effectué qu'une fois au démarrage , puis un "loop" qui est répété ad vitam.....

    Pour Calculer une moyenne glissante dans le loop, je fais ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    ...............
    Vm.dTT += sens.readTemperature();
    Vm.dTT /=2;
    ..........
    Opération repetée tous les 10secondes.
    A chaque minute, je stocke les valeurs dans un fichier ou une DB sur un Raspberry (MariaDb)

    Le soucis vient du départ du logiciel.
    Lorsque le code est effectué pour la première fois, la valeur dans Vm.dTT est la moitié de la valeur lue par le capteur.
    Il faut alors écrire une boucle pour vérifier si l'on est au premier passage ou aux suivants......
    Pour palier cela, il est simple de faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Vm.dTT = sens.readTemperature();
    dans le setup.

    Oui mais :
    Si je déclare
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    struct ValeurMinute Vm;
    dans le "Loop", je ne peut utiliser Vm dans le setup...
    Si je declare Vm dans le setup, Cette variable n'existe pas dans le loop.......

    De plus, si j’enchaîne le passage de fonction,
    Main() -> menu() ->MetEnForme()->affiche()
    Je dois chaque fois passer le pointeur pour chaque appel de fonction ....?

    Si j'ai plusieurs variables à passer à mes fonctions, leur déclarations devient vite complexe.(C'est là qu'on devient fainéant ???)

    Comme je programme tout seul dans mon petit coin et vu la structure de l'Arduino, les variables globales me semble une solution(de feignasse) simple à écrire.

    Si je pouvais avoir des avis sur la question....

    Un grand merci


    Michel

  2. #2
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 768
    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 768
    Par défaut
    Je n'ai pas bien compris ton problème (<- édit: Bktero mon voisin du dessous a répondu les fonctions setup et loop sont spécifiques à Arduino, que je ne connais pas du tout)

    Mais "passer 1 pointeur" s'appelle de l'injection de dépendances (Wikipédia français et anglais)

    Citation Envoyé par michel.semal Voir le message
    Je dois chaque fois passer le pointeur pour chaque appel de fonction ....?
    ben ouais, cela s'appelle du découplage (<- lien Wikipédia) … et c'est l'avantage de l'injection de dépendances et l'inconvénient MAJEUR des variables globales/ "god object" (<- lien Wikipédia)

    Citation Envoyé par michel.semal Voir le message
    Si j'ai plusieurs variables à passer à mes fonctions, leur déclarations devient vite complexe.(C'est là qu'on devient fainéant ???)
    il faut regrouper les paramètres dans des ""objets"" (en C, on n'a que les structures) et passer les pointeurs sur 1 ""objet"".
    Ensuite, 1 ""objet"" peut avoir du sens dans la conception de ton programme (représenter tel ou tel "concept") ou alors c'est juste 1 DTO (Data Transfert Object) (<- lien Wikipédia en anglais, en gros c'est 1 objet sans logique sauf de données)

    Après tu as la solution intermédiaire entre les variables globales et l'injection de dépendances : le gros "god object" créé dans la fonction main (donc pas global et c'est le premier truc créé et initialisé dans le programme) et que tu passes partout
    Édit: c'est d'ailleurs 1 peu le code du message #4 de @dalfab : on court-circuite la fonction setup en créant 1 nouvelle fonction initialisation, on créé toutes les variables au début de la fonction loop et ensuite, on les passe partout.

  3. #3
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    De manière générale, les variables globales, c'est nul. Ca semble une bonne idée au début parce que c'est pratique, mais avec le temps, ça devient le bazar.

    Le cas d'Arduino est un peu spécial. Si tu veux accéder à des variables dans setup() et dans loop(), tu n'as pas trop de le choix. Tu es obligé de les déclarer hors des fonctions, au niveau fichier. Tu peux ajouter static pour limiter le scope toutefois.

  4. #4
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Bonjour,

    C'est cette décomposition de l'Arduino en 2 fonctions disjointes qui empêche de faire les choses proprement.
    On peut contourner le problème en faisant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void setup(void) {
    }
    void loop(void) {
        // définitions des variables d'application partagées entre setup() et loop().
     
        initialisation( passage_par_pointeur_des_données_necessaires );  // ce qu'il y avait dans setup
        for (;;) {
            actions_cycliques( passage_par_pointeur_des_données_necessaires); // ce qu'il y avait dans loop()
       }
       // donc la fonction loop() n'est finalement appelée qu'une seule fois, c'est main()! 
    }
    On a alors plus besoin de globales sauf pour les données accédées par les interruptions où c'est alors incontournable.

  5. #5
    Membre Expert

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 633
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 633
    Par défaut
    Bonjour,

    Si les variables globales posent problème, les bannir systématiquement avec la technique du "passe à ton voisin" de fonction en fonction présentent de nombreux risques.

    Le premier est la lisibilité car cela induit un accroissement du nombre d'arguments qui rend plus difficile de trouver ce qui est propre à la fonction. Or la lisibilité et la maintenance se tiennent par la main.

    Le second est l'effet de chaîne notamment s'il y a des pointeurs, et il y en a toujours. Quand ça commence à tanguer, le pistage d'erreur mérite bien son nom. Sans aucun recul, on peut continuer à se moquer de ces temps archaïques de la programmation spaghetti.

    Le troisième est la surcharge que cela induit au niveau de la pile. Je sais que beaucoup pensent que les ressources sont quasi infinies (et les microcontrôleurs ?), mais outre la consommation de ressources mémoires, une gestion lourde de la pile prend du temps.

    Tout ceci pour dire qu'il est bien de tenir compte des risques de chaque pratique mais de ne pas en faire des règles absolues qui engendrent, d'une part un manque de réflexion (j'ai été dans le mur mais j'ai bien suivi la ligne blanche), et d'autre part des contorsions qui peuvent être plus dangereuses que ce que les règles sont censées éviter.

    Je considère que les règles sont seulement des barrières dont le franchissement doit être murement réfléchi et justifié. Cela ne va pas au-delà.

    Salutations

  6. #6
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 768
    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 768
    Par défaut
    Citation Envoyé par Guesset Voir le message
    Le premier est la lisibilité car cela induit un accroissement du nombre d'arguments qui rend plus difficile de trouver ce qui est propre à la fonction. Or la lisibilité et la maintenance se tiennent par la main.
    Les paramètres font partie de la compréhension. Par exemple, avec 1 fonction write, tu attends 1 "destination" et 1 "origine".
    Justement, avec les variables globales, tu vas n'avoir [par exemple] qu'1 fonction write sans paramètres destination ? origine ?
    Après sûrement que cela dépend de comment tu conçois ton code.

    Citation Envoyé par Guesset Voir le message
    Le second est l'effet de chaîne notamment s'il y a des pointeurs, et il y en a toujours.
    Étant expert, tu sais bien qu'1 passage par adresse/ sortie ou entrée-sortie, n'induit pas forcément 1 pointeur.
    On manipule 1 objet au travers de son adresse, mais cela n'implique pas forcément 1 allocation mémoire (avec malloc, realloc, calloc, …)

    C'est pour cela, en mon sens que la notion d'alias & du C++ est mieux : on manipule 1 objet normalement et le compilation ""fait la translation"" avec son adresse pour nous.

    Citation Envoyé par Guesset Voir le message
    Le troisième est la surcharge que cela induit au niveau de la pile.
    Si tu créés des ""objets"" pour ton code, tu vas être forcément obligé de les passer en paramètre … et en C, cela veut dire 4 (32 bits) ou 8 (64 bits) octets sur la pile.
    Et (comme je l'ai dit avant) si tu as des paramètres hétéroclites, tu crées des DTO.
    Après sûrement que cela dépend de comment tu conçois ton code : limiter le nombre de paramètres, faires les bonnes structures, créer des DTOs (ou autres), …

  7. #7
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Guesset Voir le message
    Le troisième est la surcharge que cela induit au niveau de la pile. Je sais que beaucoup pensent que les ressources sont quasi infinies (et les microcontrôleurs ?), mais outre la consommation de ressources mémoires, une gestion lourde de la pile prend du temps.
    C'est intéressant et important de s'intéresser aux conséquences, mais il ne faut pas non plus tomber dans la paranoïa. Sur bien des processeurs modernes, beaucoup de paramètres sont passés par des registres. Prenons par exemple un code comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    static int value;
    void set(int* p);
    void print(int v);
     
    int main() {
        set(&value);
        print(value);
    }
    Avec Compiler Explorer, on peut voir que le paramètre de la fonction est dans un registre.

    • Pour x64, Windows utilise 4 registres avant d'utiliser de la pile pour les paramètres
    • Linux, c'est 6 registres !
    • Pour ARM (au moins en 32 bits), c'est aussi 4 registres


    L'appel de fonction lui-même est donc potentiellement plus coûteux que quelques pointeurs en paramètres.

Discussions similaires

  1. Variable globale ou passage de variable ?
    Par Invité dans le forum Langage
    Réponses: 5
    Dernier message: 14/06/2014, 01h27
  2. Réponses: 10
    Dernier message: 27/06/2008, 14h16
  3. Réponses: 2
    Dernier message: 18/12/2006, 18h03
  4. Petit prob de passage par pointeur
    Par leCcsympas dans le forum C
    Réponses: 6
    Dernier message: 06/12/2006, 09h36
  5. Réponses: 22
    Dernier message: 23/11/2006, 23h42

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