Bonjour,
Je travaille sur les échanges de données sur le port série ; carte UNO + shield Adafruit LCD + 5 boutons en I²C.
Depuis plusieurs heures je cherche à comprendre comment fonctionnent les variables chaînes de caractères.
Voir croquis d'essai ci-dessous.
A la ligne 11, j'initialise une variable char mess[] = "Initialisation"; que j'affiche à la ligne 24, dans le setup(). OK.
Dans la boucle loop() je change le texte de cette même variable à plusieurs reprises après les if, selon le bouton sollicité. OK aussi, le bon texte s'affiche pour chaque bouton.
Par contre, en ligne 67 je lance la même commande d'affichage. Et là, il m'affiche le mot "Initialisation", c'est à dire le texte de la première déclaration, alors que je m'attendais à une répétition du dernier texte déclaré !... Comment est-ce possible ?
A chaque nouvelle déclaration (char mess[] = "xxxx";), le système occupe-t-il un nouvel emplacement mémoire ? Si oui, comment le libérer après chaque utilisation pour éviter de la saturer ?
Merci d'avance pour vos éclaircissements.
@+
Pierre
Quand tu fait char mess[] = "Initialisation"; le compilateur crée un tableau de caractères qui contient les caractères initialisation et terminé par 0. Cette syntaxe n'est valable que pour ca définition de la variable.
Quand par la suite tu fais de nouveau char mess[] = "xxxxxxx" tu définis une autre variable qui n'a rien à voir avec la variable globale que tu as défini précédemment. Donc son contenu n'est pas modifié.
En fait, c'était un exemple pour comprendre, je n'utiliserai pas ma variable mess[] pour l'envoyer à la console (Serial.println...) mais pour l'utiliser dans un autre contexte. Mais j'ai bien compris la question de la variable globale différente de la variable locale utilisée plus loin. Je suis étonné que le compilateur n'alerte pas pour ce genre de doublon ! Bon, il faut le savoir....
Par contre, que signifie exactement la syntaxe : const char *mess = "Initialisation"; (à part que c'est une constante char) ? Le rôle de l'astérisque ?
Ça veut dire qu'il y aura un 0 en fin de chaîne, après le dernier caractère, donc 15 octets plus loin en mémoire. Correct ?
Maintenant, si tu dis un peu plus loin
mess = "chaine";
Les nouveaux caractères remplacent les anciens et un 0 se place après le 5ème. Toujours bon ?
Mais le reste de la mémoire peut être utilisé pour d'autres variables, notamment l'espace disponible après les caractères de la première chaîne "Initialisation".
Donc si je fais ensuite
mess = "très longuuuuuuuuuuuuuuuuuue chaine";
Les variables situées après la chaîne initiale risquent d'être corrompues, non ?
Ça veut dire qu'il y aura un ZÉRO en fin de chaîne, après le dernier caractère, donc 15 octets plus loin en mémoire. Correct ?
Bien entendu. Avec ou sans pointeur la chaîne "Initialisation" est terminée par zéro.
"Initialisation" est une chaîne quelque part en mémoire, elle n'est pas associée à un symbole.
Le pointeur contient simplement l'adresse de cette chaîne.
Les nouveaux caractères remplacent les anciens et un 0 se place après le 5ème. Toujours bon
Non. On affecte au pointeur l'adresse d'une autre chaîne terminée par ZÉRO.
// cette chaîne est associée (au lien) à un symbole msg1.
char msg1[] = "blabla";
// cette chaîne n'est pas associée à un symbole, bien qu'elle existe en mémoire.
// Seul le pointeur msg1 existe en tant que symbole.
char *msg1 = "blabla";
Oui, bien sûr.
Je trouve ça dommage d'ailleurs. Sur pas mal d'autres processeurs (STM32, ARM, etc.), il suffit de préciser const pour que la variable soit en FLASH, sans recopie au démarrage.
Oui, effectivement quand j'ai commencé avec l'arduino, j'ai été très surpris de voir qu'on ne pouvait pas adresser directement les constantes en flash et quelles étaient recopiées en ram.