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 :

Test avec le préprocesseur


Sujet :

Arduino

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    952
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 952
    Par défaut Test avec le préprocesseur
    Hello,

    Ce petit programme me rend fou... Il y a le calcul du nombre d'éléments de deux tables (c'est un truc qu'on utilise le plus souvent possible en embarqué pour ne pas créer de variables). Puis vient ensuite la partie de code préprocesseur qui est sensée comparer les deux tailles et générer une erreur si elles sont différentes. C'est la partie que j'avoue ne pas gérer, bien que ce soit du C plus que standard. mais:

    - Si on commente les trois lignes de préprocesseur, la fonction setup() affiche correctement les 2 tailles.
    - Si je remplace les 2 tailles par des nombres différents, le code fonctionne et signale l'erreur.

    J'en conclus qu'il y a un truc que je n'ai as compris dans le #if, mais quoi? Mon code à l'air de ressembler à tout ce que j'ai vu sur le sujet.

    A+

    Pfeuh

    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
     
    typedef bool (*callback)();
     
    bool f_a(){Serial.print("function a invoked\n");return false;}
    bool f_b(){Serial.print("function b invoked\n");return false;}
    bool f_c(){Serial.print("function c invoked\n");return false;}
     
    const callback userFunctions[] PROGMEM
    {
        f_a,
        f_b,
        f_c,
    };
    #define NB_USER_FUNCTIONS (sizeof(userFunctions) / sizeof(callback))
     
    const char userFname1[]  PROGMEM = ("fct_a");
    const char userFname2[]  PROGMEM = ("fct_b");
    const char userFname3[]  PROGMEM = ("fct_c");
     
    const char *const userFunctionNames[] PROGMEM =
    {
        userFname1,
        userFname2,
        userFname3,
    };
    #define NB_USER_FUNCTION_NAMES (sizeof(userFunctionNames) / sizeof(char*))
     
    #if (NB_USER_FUNCTION_NAMES != NB_USER_FUNCTIONS)
    #error Not same number of functions and function's names for user's commands
    #endif
     
    void setup()
    {
        Serial.begin(9600);
        Serial.print(NB_USER_FUNCTIONS);
        Serial.print(F(" functions in the jump table\n"));
        Serial.print(NB_USER_FUNCTION_NAMES);
        Serial.print(F(" strings in the string table\n"));
        pinMode(LED_BUILTIN, OUTPUT);
    }
     
    void loop()
    {
        if(millis() & 0x200)
            digitalWrite(LED_BUILTIN, 0);
        else
            digitalWrite(LED_BUILTIN, 1);
    }

  2. #2
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 921
    Par défaut
    A mon avis ça ne compilera pas:
    • il manque un = pour userFunctions
    • le #if requiert quelque chose qui s'évalue comme constexpr et sizeof n'est pas un opérateur autorisé (parce que sizeof est calculé une fois que le pré-processeur a fini son travail)



    En C++ la bonne façon de faire c'est d'utiliser assert. par exemple
    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
    #include <assert.h>
     
    int a1[] = {1, 2, 3, 4};
    int b1[] = {2, 4, 8, 16};
     
    // vérification de cohérence
    static_assert((sizeof a1 / sizeof a1[0]) == (sizeof b1 / sizeof b1[0]), "Erreur, les tableaux doivent avoir la même taille");
     
    void setup() {
      Serial.begin(115200);
      Serial.println(a1[0]);
      Serial.println(b1[0]);
    }
     
    void loop() {}
    la compilation va bien se passer et si vous rajoutez un élément au tableau b1 par exemple, vous verrez que ça ne compile pas et que le message d'erreur est affiché:
    static assertion failed: Erreur, les tableaux doivent avoir la même taille

    Le code ci dessus occupe 188 octets des mémoire vive si vous le compilez sur un UNO

    Maintenant si vous déclarez des constantes et que vous les utilisez, par exemple:
    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
    #include <assert.h>
     
    int a1[] = {1, 2, 3, 4};
    int b1[] = {2, 4, 8, 16};
     
    constexpr byte tailleA1 = sizeof a1 / sizeof a1[0];
    constexpr byte tailleB1 = sizeof b1 / sizeof b1[0];
     
    // vérification de cohérence
    static_assert(tailleA1 == tailleB1, "Erreur, les tableaux doivent avoir la même taille");
     
    void setup() {
      Serial.begin(115200);
      Serial.println(tailleA1);
      Serial.println(tailleB1);
    }
     
    void loop() {}
    on a toujours la vérification de cohérence qui fonctionne bien sûr et on utilise toujours 188 octets de RAM
    --> L'optimiseur dégagera les constantes si elles ne sont pas utilisées dans le code et si elles sont utilisées mais tiennent sur 1 octet, il y a des chances pour qu'il n'alloue pas de variables et remplace directement par la valeur dans l'assembleur généré. c'est ce qu'il se passe ici.

  3. #3
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    952
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 952
    Par défaut
    Citation Envoyé par Jay M Voir le message
    sizeof n'est pas un opérateur autorisé (parce que sizeof est calculé une fois que le pré-processeur a fini son travail)
    Cette explication se passe de tout commentaire. Alors, bien sûr, pas le choix, je vais utiliser la macro assert(). Merci d'avoir pris le temps de comprendre le problème.

    A+

    Pfeuh

  4. #4
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 921
    Par défaut
    C’est la bonne façon de faire en C++ (ce n’est pas une macro, ça fait partie du langage)

    Comme mentionné il ne faut pas avoir peur d’utiliser des constantes calculées à la compilation et laisser l’optimiseur faire son boulot plutôt que de mettre des define qu’il vaut mieux réserver pour la compilation conditionnelle par exemple

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

Discussions similaires

  1. Test avec Junit, Mock
    Par LESOLEIL dans le forum Tests et Performance
    Réponses: 2
    Dernier message: 27/03/2006, 18h03
  2. [Mail] Construire un test avec une variable
    Par jeromesco dans le forum Langage
    Réponses: 3
    Dernier message: 17/02/2006, 21h52
  3. [xsl] Test avec une variable ?
    Par maxonman dans le forum XSL/XSLT/XPATH
    Réponses: 8
    Dernier message: 24/01/2006, 10h47
  4. outils d'automatisation de test avec PHP
    Par ss dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 4
    Dernier message: 22/12/2005, 14h33
  5. xsl:test .... avec comportement bizarre
    Par Blue LC dans le forum XMLRAD
    Réponses: 2
    Dernier message: 10/06/2005, 13h56

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