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

Arduino Discussion :

Un Warning à la compilation


Sujet :

Arduino

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 Un Warning à la compilation
    Bonjour,

    J'étudie des nouvelles pistes (nouvelles pour moi hein )
    L'idée est de cree des menu dans le terminal.
    Pour faire cela, je dois passer des pointeurs sur des chaines de caractères.

    Je defini donc les chaines comme globales
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char *MaChaine[] = {"  1 = Menu 01",
                         "  2 = Menu 02",
                         "  3 = Menu 03",
                         "  4 = Menu 04"
                          };
    je fais passer ces pointeurs comme pointeur de pointeur dans l'entête de mon fichier (menu.h), le prototype de la fonction est donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    ;
    ;
    extern void GetChar(byte *,char **,int);
    .
    .
    .
    Je passe donc un byte* pour recuperer le resultat, le char ** qui pointe sur mon tableau de pointeur, et le nombre déliements contenu dans mon tableau de pointeur int

    Pour afficher mes chaines, depuis la fonction GetChar(), j'apelle une autre fonction donc la déclaration est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    void menu00( byte *,char **,int);
    ..
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void menu00( byte *pEtatMenu,char** pMenu,int NbElements){
     for(int i=0;i<NbElements;i++){
        Serial.println(pMenu[i]);
      }
    .....
    }
    Et dans cette fonction j'affiche les diverses chaine via les pointeur pMenu[i] avec le 'i' pour boucler sur tous les pointeurs.

    Tous se passe bien, mais à la compilation j'ai les message:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
                           };
    Je comprend +/- l'erreur, j'ai défini mes chaines de caractère comme constante, et je suppose que je les affiche comme variable.

    Mais comment lever cette erreur?

    J'ai deja essaye des "trucs", avec des cast (const) un peu partout, mais il reste toujours des erreurs (pas toujours les même d’ailleurs.

    Si quelqu'un pouvait éclairer ma lanterne....

    Un grand merci

    Bonne fêtes à tous

    Michel

  2. #2
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 913
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 913
    Par défaut
    la raison de vos warnings est sans doute dû au faite que lorsque l'on déclare un pointeur vers une chaîne entre guillemets la norme dit que ces données sont potentiellement rangées dans un segment non modifiable de la mémoire et donc sont constantes.

    Par exemple si vous faites
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char* uneChaine = "bonjour";
    alors la norme dit que vous n'avez pas le droit de modifier le 'b' en 'B' par exemple en faisant ou encore même si certaines implémentations (par exemple sur petits Arduinos) mettent effectivement les données en SRAM et donc c'est modifiable et ça fonctionnera.

    essayez ce code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    char* uneChaine = "bonjour";
     
    void setup() {
      Serial.begin(115200);
      Serial.println(uneChaine);
      *uneChaine = 'B';
      Serial.println(uneChaine);
    }
     
    void loop() {}
    dans la console à 115200 bauds vous verrez bien
    bonjour
    Bonjour

    donc le b a été changé en B

    mais à la compilation vous aurez eu un warning:
    sketch_dec27b.ino:1:19: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
    char* uneChaine = "bonjour";
    ^~~~~~~~~


    qui vous dit qu'en C++ (la norme ISO C++) vous n'avez pas le droit de modifier le contenu pointé par ce pointeur.

    pour écrire correctement en respectant la norme il faut dire que les données pointées par le pointeur sont constantes et donc on doit écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const char * uneChaine = "bonjour";
    
    void setup() {
      Serial.begin(115200);
      Serial.println(uneChaine);
      *uneChaine = 'B';
      Serial.println(uneChaine);
    }
    
    void loop() {}
    et ce coup ci, si vous essayez de compiler alors le compilateur met une erreur et pas un warning

    sketch_dec27b.ino: In function 'void setup()':
    sketch_dec27b:6:16: error: assignment of read-only location '* uneChaine'
    *uneChaine = 'B';
    ^~~
    exit status 1
    assignment of read-only location '* uneChaine'


    La déclaration des types est donc très importante. il faut être conforme à la norme généralement, même si GCC est permissif car il sait que les données sont en SRAM et donc ne m'a pas interdit d'utiliser le premier code puisqu'il est fonctionnel, il m'a juste dit que je ne respectais pas la norme et donc que je prenais des risques et qu'il ne garantissait pas le bon fonctionnement.

    ----------------

    Dans votre cas, votre premier tableau contient des pointeurs vers des chaînes définies entre guillemets, et donc quand vous déclarez
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char *MaChaine[] = {
      "  1 = Menu 01",
      "  2 = Menu 02",
      "  3 = Menu 03",
      "  4 = Menu 04"
    };
    le compilateur n'est pas d'accord avec vous, pour lui le type correct serait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    const char *MaChaine[] = {
      "  1 = Menu 01",
      "  2 = Menu 02",
      "  3 = Menu 03",
      "  4 = Menu 04"
    };
    car vous avez dans le tableau des pointeurs vers des caractères constants.


    En pratique même vos pointeurs sont constants et vous n'avez pas besoin de les modifier donc le type de votre tableau devrait être const char * const

    Essayez de regarder ce bout de code
    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
    49
    50
    51
    52
    53
    54
    const char * const lesMenus[] = {
      "  1 = Menu 01",
      "  2 = Menu 02",
      "  3 = Menu 03",
      "  4 = Menu 04"
    };
    const byte nombreDeMenus = sizeof lesMenus / sizeof lesMenus[0];
     
    const byte lesDonnees[][5] = {
      {0, 1, 2, 3, 4},        // pour menu 1
      {5, 6, 7, 8, 9},        // pour menu 2
      {10, 11, 12, 13, 14},   // pour menu 3
      {15, 16, 17, 18, 19},   // pour menu 4
    };
     
    void printMenus(const char * const * menus, int taille)
    {
      Serial.println(F("---- LES MENUS ----"));
      for (byte i = 0; i < taille; i++) {
        Serial.println(menus[i]);
      }
      Serial.println(F("----------------"));
    }
     
    const byte * obtenirDonnees(const char *  const * menus, int taille)
    {
      int resultat = -1;
      for (byte i = 0; i < taille; i++) {
        if (! strcmp(menus[i], "  3 = Menu 03")) { // on recherche un menu ici codé en dur
          Serial.println(F("\n\tTrouvé menu 3\n"));
          resultat = i;
          break;
        }
      }
      if (resultat != -1) return lesDonnees[resultat];
      return NULL;
    }
     
    void setup()
    {
      Serial.begin(115200);
      printMenus(lesMenus, nombreDeMenus);
     
      const byte * mesDonnees = obtenirDonnees(lesMenus, nombreDeMenus);
      if (mesDonnees != NULL) {
        Serial.println(F("---- LES DONNEES ----"));
        for (byte i = 0; i < 5; i++) {
          Serial.println(mesDonnees[i]);
        }
        Serial.println(F("----------------"));
      }
    }
     
    void loop() {}
    (à lancer avec la console à 115200 bauds)

    les types se lisent de droite à gauche, par exemple quand j'écris
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    const char * const lesMenus[] = {
      "  1 = Menu 01",
      "  2 = Menu 02",
      "  3 = Menu 03",
      "  4 = Menu 04"
    };
    je dis que j'ai un tableau [] qui s'appelle lesMenus dont le type de chaque élément est un constant (const) pointeur (*) vers des charactères (char) qui sont constants (const).

    ou alors dans les fonctions je ne passe pas un tableau, juste le pointeur donc je dis que le type est const char * const * c'est à dire un pointeur (*) constant (const) vers un pointeur (*) vers des caractères (char) constants (const).

    ==> toujours bien typer ces données et lire le type de droite à gauche.

    est-ce que ça vous aide?

  3. #3
    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
    Bonjour Jay M

    Merci pour les infos,

    J'avoue que lorque l'on commence a multiplier les pointeurs sur des pointeurs sur des const sur des chaines sur des char,..... je me perd un peu

    Je me doutait bien que le problème était dans le "typage" de mes variables (même si elle sont constantes.........)

    J'ai suivit tes explications, je pense les avoir comprises.... et je les ai appliquées.

    Du coup, plus de Warning

    Les corrections
    Dans le Menu.ino :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    const char  * const MaChaine[] = {
          "  1 = Menu 01",
          "  2 = Menu 02",
          "  3 = Menu 03",
          "  4 = Menu 04"
          };
    Dans le menu.h:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void menu00( byte *,const char *const *,int);
    void menuUp( byte *,const char *const *,int);
    void GetChar(byte *,const char * const *,int);
    void Menu(const char *const *,int);
    ]

    Et pour finir dans chaque declaration de fonction elles sont devenue du syle :

    dans le Menu.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    void GetChar (byte *pEtatMenu, const char* const * pMenu, int NbElements){
    .....
    }
    Dès lors, plus de warning à la compilation.


    Le but final étant de faire une bibliothèque avec les menus, je ne voudrais pas que cette bibliothèque amènes des warning lors de la compilation.

    Un tout grand merci,

    Je note comme résolu.

    Michel

  4. #4
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 913
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 913
    Par défaut
    Très bien - oui il faut être concentré quand on écrit ou lit un type. Si on prend l'habitude de lire de droite à gauche, on s'y retrouve.

    Si vos fonctions qui ont une valeur de retour (que vous passez avec un byte*) vous pouvez retourner directement cela en enlevant le void et en mettant le type à retourner (et faire un return dans la fonction)

  5. #5
    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
    C'est en effet la prochaine étape.

    J'analyse pour voir ce qui est le mieux (en place mémoire), soit passer un pointeur sur un byte , soit retourner une valeur, la fonction appelante prendra alors la forme :

    la fonction appelante dois alors elle aussi gere un retour vers le "main" du programme

    Je cherche a rendre mon code le plus "efficace" cad le moins consommateur de mémoire pour les carte arduino.

    donc je modifie, note les gain/perte, remodifie, etc.
    Cela prend du temps mais c'est amusant à faire.

    Donc des conseils sont surement les bien venus

    Merci

    Michel

  6. #6
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 913
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 913
    Par défaut
    Ok

    Le premier conseil alors serait de mettre les textes en mémoire programme (cf PROGMEM)

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

Discussions similaires

  1. Enlever les warnings à la compilation
    Par piotrr dans le forum Général Java
    Réponses: 3
    Dernier message: 29/10/2007, 19h02
  2. [GCC] warning de compil
    Par AcidBurn37 dans le forum C
    Réponses: 2
    Dernier message: 22/10/2007, 13h11
  3. problème de warning en compilant win32 + directx
    Par madcode dans le forum VC++ .NET
    Réponses: 4
    Dernier message: 17/10/2006, 16h58
  4. Réponses: 8
    Dernier message: 23/08/2006, 18h40
  5. Petits warnings apres compilation sous Solaris
    Par Thordax dans le forum C++
    Réponses: 22
    Dernier message: 04/07/2006, 09h45

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