Go Down

Topic: Les pointeurs et tableaux (Read 15150 times) previous topic - next topic

osaka


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.   ;)


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


Et ce qui ce cachait derrière l'indexation aussi, manipuler tes tableaux via '*' ?  :smiley-mr-green:

Gromain59

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 :)

@+ pour d'autres tuto ?

Gromain
"pour résoudre un gros problème, il est souvent plus facile de le diviser en petits problèmes élémentaires..."

projet domotique xPLDuino
IRC: freenode #xplduino

nulentout

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 :
Code: [Select]
/* >>>>>>>>>>>>>>>>>>> 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 :
Code: [Select]

/* 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.

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy