Les pointeurs et tableaux

Yop yop,
Comme il a l'air d'être très demandé, je prépare un tutoriels sur l'utilisation des pointeurs et tableaux.

tuto_pointeurs.pdf (826 KB)

Page 9

void?loop()?
{?
? int? maVariable?=?20;?
? int* ?monPointeur1?=??&maVariable;?
? int* ?monPointeur2?=?monPointeur1;?
}

Mon ?deuxième ?pointeur ?aura ?pour ?valeur ?la ?même? adresse ?que ?mon ?premier? pointeur?
et ?pointera ?donc ?sur ?la ?même ?variable.?

C’est? comme? si ?j’avais ?fait ?ceci ?avec ?une ?variable ?classique?:?
? int ?maVariable1?=?20;?
? int? maVariable2?=?maVariable1?;?

Ma? deuxième ?variable ?prend? la ?même ?valeur ?(20) ?que ?la ?première,? pour ?les? pointeur? c’est ?pareil ??CQFD.?

Le parallèle est dangereux et peut entraîner des incompréhensions de la part des débutants. Dans le cas de ?maVariable1? et ?maVariable12, elles ont chacune leur vie propre et modifier l'une ne change pas l'autre. Alors qu'avec les pointeurs ce n'est pas le cas, les 2 pointeurs pointent sur la même variable.

PS: Après viendras la correction aurtaugrafik, j'ai la chance d'avoir une compagne qui est secrétaire de direction à portée de clavier.

Ben elle va pas chômer. On sent que tu entretiens des rapports assez conflictuels avec les infinitifs et les participes passés.

Autrement pour être constructif. Je pense (mais cet avis est personnel) que pour la clarté de la lecture il est préférable d'avoir les renvois en bas de page et non pas en fin de document. Cela évite les aller et retour entre la page en cours de lecture et la page des renvois.
Il faudra aussi aborder l'arithmétique des pointeurs.

Bien,
J'ai de la lecture pour les jours de pluie.
Merci

fdufnews:
Le parallèle est dangereux et peut entraîner des incompréhensions de la part des débutants.

Yop yop,

C'est pour cela que je précise bien qu'il s'agit de la valeur du pointeur, il faudra peut être encore plus insisté sur ce point et rajouter un petit schéma ou autre pour ce cas là ?

fdufnews:
Dans le cas de ?maVariable1? et ?maVariable2, elles ont chacune leur vie propre et modifier l'une ne change pas l'autre. Alors qu'avec les pointeurs ce n'est pas le cas, les 2 pointeurs pointent sur la même variable.

Disons que là je parle bien du pointeur en temps que variable (d'où le comparatif) donc qui ont également leur vie propre, je peux modifier la valeur de l'un ou l'autre ou même supprimer l'un ou l'autre ou les deux ça ne change rien pour la variable pointée.
Je vais quand même regardé à bien clarifié la chose.
Grand merci pour ton retour. :slight_smile:

Quelques changements, j'ai tenté de clarifier certaines choses et ajouter quelques schémas (donc plus lourd :~).
Est-ce plus accessible pour les débutants ?

Très franchement, en l'instant présent, je te fais confiance. Je pense que ça se gâtera (pour moi) quand j'aurais l'occasion de mettre en pratique

68tjs:
Très franchement, en l'instant présent, je te fais confiance. Je pense que ça se gâtera (pour moi) quand j'aurais l'occasion de mettre en pratique

Je vais essayé de mettre un maximum de schémas et exemples (j'ai ajouté un exemple pratique via arduino à la fin) et peut être quelques exercices comme il y a rien de tel que la pratique. :wink:
Là je viens de commencer les tableaux, si quelqu'un à une remarque pour savoir si je suis dans le bon ? XD

Yop Yop,
Ai bien avancé sur les tableaux, toujours pas de remarques, suggestions ?

Pour donner l'eau à la bouche :grin: et savoir si ce tuto vous seras utile, vous pouvez tester ce code et voir si la sortie console correspond bien à vos attentes :

void setup()
{
  Serial.begin(9600);
  delay(2000);
  int tab[] = {1,2,3,4};
  Serial.print("");
  Serial.print("tab :");
  Serial.println((int)tab);
  Serial.print("&tab :");
  Serial.println((int)&tab);
  Serial.print("&tab[0] :");
  Serial.println((int)&tab[0]);
  
  Serial.println("");
  
  Serial.print("tab[0] :");
  Serial.println(tab[0]);
  Serial.print("*tab :");
  Serial.println(*tab);
  Serial.print("*tab+0 :");
  Serial.println(*tab+0);
}

void loop(){}

Bonsoir,

J'ai lu attentivement ce tuto. (Difficile à suivre, pour l'instant, à cause de l'orthographe. :grin:)

C'est clair, les schémas sympas.

1/ Ne faudrait-il pas donner des règles de prononciation du genre:

int* monPointer = &maVariable;
*monPointer = 16;

du genre:
"pointeur d'entier monPointer = adresse de maVariable"
"variable pointée par monPointer = 16"

2/Pointeurs, tableaux, OK, il faudrait "enchaîner" avec les strings, non?

En tout cas, merci pour ce travail bien utile.

PS

Merci Osaka pour ce super tutoriel que je viens de découvrir, Je vais le lire attentivement, car pour l'instant je n'ai jamais réussi à mettre en oeuvre les pointeurs en C.
Alors que pour moi cela ne devrait pas être un problème de conceptualisation. Car j'ai, en son temps, pas mal programmé en assembleur en utilisant les différents modes d'adressage (indirect, indexé ...). Mais c'est plutôt les questions de syntaxe qui me font prendre les pieds dans le tapis; ce n'est probablement qu'une question d'habitude !

J'ai d'ailleurs une application toute trouvée, puisque dans mon projet de domotique, qui avance à petits pas (mais qui avance, je donnerai des nouvelles bientôt), pour l'instant pour tester le matériel j'ai défini mes plages horaires dans des tableaux, mais il va me falloir faire mieux bientôt.

Encore merci et bravo !

Brisebee:
Alors que pour moi cela ne devrait pas être un problème de conceptualisation. Car j'ai, en son temps, pas mal programmé en assembleur en utilisant les différents modes d'adressage (indirect, indexé ...). Mais c'est plutôt les questions de syntaxe qui me font prendre les pieds dans le tapis; ce n'est probablement qu'une question d'habitude !

Yop BriBri,
En effet en venant de l'assembleur et avec les petit schémas sur la mémoire, tu devrais assé vite faire le parallèle avec le code.
La chose qui perturbe le plus c'est à quel moment utilisé le petit symbole '*', comme il ne signifie pas la même chose selon l'endroit où il ce situe et quand on l'utilise.
Mais au final c'est comme tu le dis :

Brisebee:
ce n'est probablement qu'une question d'habitude !

Aucun lien vers ton PDF ne fonctionne pour moi dans ton sujet =(

UniseV:
Aucun lien vers ton PDF ne fonctionne pour moi dans ton sujet =(

Petit problème en effet :sweat_smile:, je l'ai mis en attachement dans le premier post.
:wink:

Hé bien c'est tout simplement génial, merci à toi.

En tout cas pour moi, la démystification est réussie (à noter que je manipulais déjà des tableaux).

Sev

UniseV:
Hé bien c'est tout simplement génial, merci à toi.
En tout cas pour moi, la démystification est réussie

Très sympa d'avoir un retour, grand merci à toi. :wink:

UniseV:
(à noter que je manipulais déjà des tableaux).

Et ce qui ce cachait derrière l'indexation aussi, manipuler tes tableaux via '*' ? :grin:

osaka,

merci pour ce tuto que j'avais repéré il y a un moment. Il m'a permis de rafraichir mes souvenirs.
Grâce aux pointeurs et à malloc(), j'ai pu créer dynamiquement les instances des différentes classes de mon projet :slight_smile:

@+ pour d'autres tuto ?

Gromain

Bonjour les copains, bonjour Osaka,
En premier, je tiens à saluer avec force ce travail remarquable que tu as effectué. J’ai suffisamment réalisé de documents sur ordinateur pour évaluer sans peine l’investissement que tu auras englouti à ce tutoriel. Je l’ai lu, relu, et rerererelu pour arriver à comprendre. Ce n’est pas qu’il est mal construit, au contraire, mais le sujet est assez délicat et il faut le dire « indigeste ». En réalité, non seulement j’ai suivi tes propos, mais également en parallèle toute une palanquée de sujets connexes sur Internet. Grâce à toutes ces sources, je crois avoir saisi le principal. Il reste encore des zones d’ombre, mais je ne chercherai à en percer les secrets que si mes cheminements en programmation me l’imposent. Pour le moment, je sais utiliser globalement les pointeurs, travailler avec des tableaux dynamiques, utiliser des tableaux de pointeurs. Avec tout ça on peut déjà pas mal se débrouiller.
PROPOSITIONS :
Le sujet traite de l’utilisation de la mémoire. Pour comprendre ce qui se passait avec mes pointeurs, pour moi la seule façon consistait à « regarder directement » le contenu de la RAM. Ainsi je pouvais comparer ce que j’avais cru avec la réalité. Parfois j’ai constaté que je codais l’adresse du pointeur et non l’adresse de sa CIBLE. BREF, la petite procédure de visualisation de la mémoire est pour moi un outil.
Voici cette procédure :

/* >>>>>>>>>>>>>>>>>>> Listage du contenu de la SRAM de l'ATmega328 <<<<<<<<<<<<<<<<<<<
   Le cout complet de la procédure, de son appel ainsi que le code pour lister sur la
   ligne série USB est de 2578 Octets. Pour des raisons de compacité du programme et
   pour n'avoir qu'une seule procédure à inclure au logiciel en cours de développement
   une seule procédure "entasse en ligne" toutes les instructions au détriment de la
   lisibilité. En début de procédure on définit les limites de la zone RAM à lister.
   Possibilité d'utiliser les pointeurs prédéfinis pour lister des zones spécifiques. */

void setup() {Serial.begin(115200);}

void loop() {
  LISTER_SRAM(0x180, 0x345, false );
  INFINI: goto INFINI; }
  
/* >>>>>>>>>>>>>>>>>>>>>>>>>>>> PARAMETRES DE LA PROCEDURE <<<<<<<<<<<<<<<<<<<<<<<<<< */  
/*================= Définir ci dessous les limites de la zone listée =================*/
// Modifier à convenance Les limites :
// LISTER_SRAM(DEBUT, FIN, --- );
/*============== Choisir ci dessous le listage en ASCII ou en HEXADÉCIMAL ============*/
// Par défaut liste en HEXADECIMAL. Si ASCII désiré passer à true.
// LISTER_SRAM(---, ---, false );
/*================ Lister la zone DATA avec les pointeurs prédéfinis =================*/
//Serial.print("Liste la zone DATA."); Serial.println();
//extern int __data_start , __data_end;
//int DEBUT = (uint16_t) (int*) &__data_start, FIN = (uint16_t) (int*) &__data_end;
/*================= Lister la zone BSS avec les pointeurs prédéfinis =================*/
//Serial.print("Liste la zone BSS."); Serial.println();
//extern int __bss_start , __bss_end;
//int DEBUT = (uint16_t) (int*) &__bss_start, FIN = (uint16_t) (int*) &__bss_end;
/*================= Lister le TAS HEAP avec les pointeurs prédéfinis =================*/
//  Serial.print("Liste le TAS HEAP."); Serial.println();
//  extern int __bss_end;
//  int DEBUT = (uint16_t) (int*) &__bss_end , FIN = (uint16_t) SP; 
/*====================================================================================*/ 
  
void LISTER_SRAM(int DEBUT, int FIN, boolean ASCII){
  byte *PTR = NULL; // Pointeur des octets en SRAM.
  int DEB_ZERO = DEBUT & 32752;
  PTR = (byte*) DEB_ZERO; FIN = FIN + 1;
  byte NB_LIG = 8; // Nb de lignes avant d'afficher l'entête.
  while (PTR < (byte*) FIN) {
  if (NB_LIG == 8) { NB_LIG = 0; Serial.println();
      Serial.println(" ADRS  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");}
  while (NB_LIG < 8) {
         if ((uint16_t) PTR < FIN) { 
         byte Compteur_Octets = 0; Serial.print(' ');
         if ((uint16_t) PTR < 16) {Serial.print('0');};
         if ((uint16_t) PTR < 256) {Serial.print('0');};
         if ((uint16_t) PTR < 4096) {Serial.print('0');};
         Serial.print((uint16_t) PTR,HEX); Serial.print(' ');  
         while ((Compteur_Octets < 16) && (PTR < (byte*) FIN))
               {if ((uint16_t) PTR < DEBUT) {Serial.print("   ");}
                else {Serial.print(' ');
                     if (ASCII) {Serial.print(' ');
                          if ((*PTR < 126) && (*PTR > 31)) {Serial.print(char(*PTR));}
                          else {Serial.print(char('.')); } }
                     else {if (*PTR < 16) {Serial.print('0');} Serial.print(*PTR,HEX);}}
                PTR++; // Pointer l'octet suivant.
                Compteur_Octets++; }
         Serial.println(); }
         NB_LIG++; } } }

Voici un programme d’expérimentation sur les pointeurs dans laquelle je m’en sert :

/* Utilisations des tableaux de pointeurs */
String TEXTE;

// Ci-dessous on déclare un tableau de pointeurs sur des chaînes.
char *PLANETES[] = {"Mercure", "Venus", "Terre", 
                    "Mars", "Jupiter", "Saturne", 
                    "Uranus", "Neptune", "Pluton"};

void setup() {Serial.begin(115200);}

void loop() {
  // Affiche les 9 pointeurs et leurs contenus.
  for (int I = 0; I < 9; I++) Afficher_un_pointeur(I); Serial.println();
  //  for (int I = 0; I < 9; I++) Afficher_un_pointeur(I);
  for (int I = 0; I < 9; I++) {Serial.print(PLANETES[I]);
  Serial.print(' ');}  Serial.println();
  for (int I = 2; I < 6; I++) {Serial.print(PLANETES[I]);
  Serial.print(' ');} Serial.println(); Serial.println();
  
  // Premier caractère de "Mars" remplacé par celui de "Pluton".
  *PLANETES[3] = *PLANETES[8]; Afficher_un_pointeur(3);
  *PLANETES[3] = 'M'; // Restitue le premier caractère de "Mars".
  
  /* Échanger "Venus" et "Terre" choisies car même taille */
  TEXTE = PLANETES[2]; Serial.print("TEXTE = "); Serial.println(TEXTE);
  Permute_deux_chaines(PLANETES[1],PLANETES[2]);
  Passe_chaines_dans_cible(PLANETES[1],TEXTE);
  for (int I = 0; I < 9; I++) {Serial.print(PLANETES[I]);
  Serial.print(' ');}  Serial.println();
  
  LISTER_SRAM(0x18E, 0x1CC, true );
  LISTER_SRAM(0x1CD, 0x1DE, false );
  INFINI: goto INFINI; }
  
void Passe_chaines_dans_cible(char *SOURCE, String CHAINE) {
  char *PTR_cible; PTR_cible = SOURCE; byte I = 0;
  while (CHAINE[I] != 0) {*PTR_cible++ = CHAINE[I++];} } 
  
void Permute_deux_chaines(char *SOURCE, char *CIBLE) {
  char *PTR_source, *PTR_cible; PTR_source = SOURCE; PTR_cible = CIBLE;
  while (*PTR_source != 0) {*PTR_cible++ = *PTR_source++; } }  
   
void Afficher_un_pointeur(byte I) {
  Serial.print("En $"); Serial.print((uint16_t)&PLANETES[I], HEX);
  Serial.print(" on a l'adresse du pointeur "); Serial.print(I+1);
  Serial.print(" dont la cible est en : ");
  Serial.print((uint16_t) *(&PLANETES[I]), HEX);
  Serial.print(" et contient "); Serial.println(*PLANETES[I]); }
    
 void LISTER_SRAM(int DEBUT, int FIN, boolean ASCII){
  byte *PTR = NULL; // Pointeur des octets en SRAM.
  int DEB_ZERO = DEBUT & 32752;
  PTR = (byte*) DEB_ZERO; FIN = FIN + 1;
  byte NB_LIG = 8; // Nb de lignes avant d'afficher l'entête.
  while (PTR < (byte*) FIN) {
  if (NB_LIG == 8) { NB_LIG = 0; Serial.println();
      Serial.println(" ADRS  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");}
  while (NB_LIG < 8) {
         if ((uint16_t) PTR < FIN) { 
         byte Compteur_Octets = 0; Serial.print(' ');
         if ((uint16_t) PTR < 16) {Serial.print('0');};
         if ((uint16_t) PTR < 256) {Serial.print('0');};
         if ((uint16_t) PTR < 4096) {Serial.print('0');};
         Serial.print((uint16_t) PTR,HEX); Serial.print(' ');  
         while ((Compteur_Octets < 16) && (PTR < (byte*) FIN))
               {if ((uint16_t) PTR < DEBUT) {Serial.print("   ");}
                else {Serial.print(' ');
                     if (ASCII) {Serial.print(' ');
                          if ((*PTR < 126) && (*PTR > 31)) {Serial.print(char(*PTR));}
                          else {Serial.print(char('.')); } }
                     else {if (*PTR < 16) {Serial.print('0');} Serial.print(*PTR,HEX);}}
                PTR++; // Pointer l'octet suivant.
                Compteur_Octets++; }
         Serial.println(); }
         NB_LIG++; } } }

Je pense qu’il serait certainement utile de joindre cet "outil" à ton tutoriel, ainsi tes lecteurs pourraient, comme je l’ai fait, établir le lien entre tes schémas et leur Arduino.
Par ailleurs, j’ai durant mon apprentissage résumé ce que je crois avoir compris dans un petit manuel papier assez analogue à celui sur la SYNTAXE. Je le joins à ce pst pour que tu puisses en prendre connaissance. J’ai alors deux possibilités :

  1. Le mettre en ligne avec le manuel de SYNTAXE.
  2. Tu l’ajoutes à ton tutoriel pour avoir une sorte de « Tout en main ».
    Que penses-tu de ces propositions ?
    Amicalement : Nulentout.

LES POINTEURS format tablette.pdf (198 KB)

bravo à Osaka et nulentout pour leurs documentations !
Petite erreur de frappe dans le document de nulentout sur les pointeurs, page 9 ligne 12
lire PTR =&OCTET et non pas PTR = &PTR
Cordialement

Bonjour a tous …

Je suis nouveau et débutant dans la communauté Arduino.

Même si le post du document pdf de osaka est ancien il est d’actualité.

Ce document est clair et simple en même temps Bravo a l’auteur.

Je cherche à comprendre le rouage des librairies. Ce document sur les pointeurs ‘* & ‘ et sur une partie de leur subtilités, m’ éclaire et m’emballe beaucoup.

Un grand merci à vous tous sur le forum en français…, vous qui disposer de votre temps à la porté des débutants pour les soutenir et les encourager dans leur quêtes à comprendre et a avancer dans un domaine ou les possibilités sont infini.

Larod1