Pointeur et compilation

Salut à tous,

pour vous expliquer rapidement, j’ai un écran graphique monochrome, donc j’ai créé une typo d’écriture avec, par exemple, 3 octets par caractère, puis, tous les caractères dans un pointeur tableau.

Ensuite ma fonction d’affichage laisse opérer la magie et en fonction du caractère actuel de la chaine, il affiche les bons octets au bon endroit.

Tout se passe bien lorsque tous les caractères sont différents, par contre, si ils sont identique, c’est comme si il n’y en avait qu’un dans le tableau.

Pour debugguer ce qui n’allait pas, j’affichai juste les octets des caractères.
Avec cet exemple simplifié qui fonctionne:

const unsigned char pA_5x3[3]={0xF0,0x28,0xF0};
const unsigned char pB_5x3[3]={0xF8,0xA8,0x50};
const unsigned char pC_5x3[3]={0x70,0x88,0x88};
const unsigned char pD_5x3[3]={0xF8,0x88,0x70};
const unsigned char pE_5x3[3]={0xF8,0xA8,0x88};
const unsigned char* fontChiffre5x3[]={pA_5x3,pB_5x3,pC_5x3,pD_5x3,pE_5x3};

void setup(void)
{
Serila.begin(9600);
//juste pour afficher le premier octet de chaque caractère
for(int i=0;i<12;i=i+3)
  {
  Serial.println(String(*(fontChiffre5x3+i),HEX));
  }
}

void loop(void)
{}

J’obtiens bien en sortie:
F0
F8
70
F8
F8

Par contre, si j’ai besoin de combler le tableau, et que je fait cela:

const unsigned char pRien[3]={0,0,0};
const unsigned char pA_5x3[3]={0xF0,0x28,0xF0};
const unsigned char pB_5x3[3]={0xF8,0xA8,0x50};
const unsigned char pC_5x3[3]={0x70,0x88,0x88};
const unsigned char pD_5x3[3]={0xF8,0x88,0x70};
const unsigned char pE_5x3[3]={0xF8,0xA8,0x88};
const unsigned char* fontChiffre5x3[]={pA_5x3,pRien,pRien,pRien,pE_5x3};

void setup(void)
{
Serila.begin(9600);
//juste pour afficher le premier octet de chaque caractère
for(int i=0;i<12;i=i+3)
  {
  Serial.println(String(*(fontChiffre5x3+i),HEX));
  }
}

void loop(void)
{}

Alors j’obtiens en sortie:
F0
0
F8

Il manque donc les autres caractères.

Pour contrer ca, j’ai du déclarer d’autres variables:

const unsigned char pRien1[3]={0,0,0};
const unsigned char pRien2[3]={0,0,0};
const unsigned char pRien3[3]={0,0,0};
const unsigned char pA_5x3[3]={0xF0,0x28,0xF0};
const unsigned char pB_5x3[3]={0xF8,0xA8,0x50};
const unsigned char pC_5x3[3]={0x70,0x88,0x88};
const unsigned char pD_5x3[3]={0xF8,0x88,0x70};
const unsigned char pE_5x3[3]={0xF8,0xA8,0x88};
const unsigned char* fontChiffre5x3[]={pA_5x3,pRien1,pRien2,pRien3,pE_5x3};

void setup(void)
{
Serila.begin(9600);
//juste pour afficher le premier octet de chaque caractère
for(int i=0;i<12;i=i+3)
  {
  Serial.println(String(*(fontChiffre5x3+i),HEX));
  }
}

void loop(void)
{}

Alors j’obtiens en sortie:
F0
0
0
0
F8

Quelqu’un a une idée du pourquoi du comment?

Merci à vous

tu as essayé pRien[3]={0x00,0x00,0x00}; ?

oui, essayé, mais ca ne change rien

Bonjour,

Ton code ne compile pas. Il y a une typo sur Serial dans Serial.begin et le constructeur de String n’accepte pas un const unsigned char*&

Quoiqu’il en soit : La boucle va parcourir le tableau fontChiffre5x3 de 3 en 3 et tourne 4 fois. Les éléments 0, 3, 6 et 9 de fontChiffre5x3 sont donc accédés, c’est à dire pA_5x3, pD_5x3, puis ce qui traine en mémoire après la fin du tableau puisque l’index déborde. L’élément récupéré est un pointeur d’unsigned char. Si on suppose que le constructeur de String le déréférence (mais je ne sais pas lequel est appelé), on va récupérer le premier caractère de pA_5x3 (F0) puis celui de pD_5x3 (F8). Pour la suite c’est un grand mystère.

Pourquoi ton premier programme fonctionne (mais il ne compile pas) ? il faudrait savoir en quoi tu as casté ton *(fontChiffre5x3+i) pour que ça compile.

Pour corriger le programme, il faut parcourir le tableau fontChiffre5x3 de 1 en 1. Ce tableau contient des pointeurs vers le premier octet de chacun de tes caractères et pas les caractères eux-même. Pour accéder au caractère pointé, on déréférence le pointeur comme ceci

*fontChiffre5x3[i]
const unsigned char pA_5x3[3]={0xF0,0x28,0xF0};
const unsigned char pB_5x3[3]={0xF8,0xA8,0x50};
const unsigned char pC_5x3[3]={0x70,0x88,0x88};
const unsigned char pD_5x3[3]={0xF8,0x88,0x70};
const unsigned char pE_5x3[3]={0xF8,0xA8,0x88};
const unsigned char* fontChiffre5x3[]={pA_5x3,pB_5x3,pC_5x3,pD_5x3,pE_5x3};

void setup(void)
{
  Serial.begin(9600);
  //juste pour afficher le premier octet de chaque caractère
  for(int i=0;i<5;i++)
  {
    Serial.println(String(*fontChiffre5x3[i],HEX));
  }
}

void loop(void)
{
}

Salut,
en fait j'ai un peu triché, ce n'est pas le code que j'ai fait que je vous ai montré, mais une version simplifié,juste pour comprendre le principe. Et je ne l'ai pas testé.
En fait , comme je peux avoir plusieurs police d'écriture, j'utilise une structure de police, et ainsi je passe à ma fonction la bonne structure pour qu'elle utilise la bonne police.
Donc mon code compile corretcement,
c'est juste le placement en mémoire que je ne comprend pas, car si j'affiche chaque octets des caractères, quand le caractère se repete, alors il n'est pas placé en mémoire.

Peux-tu mettre le vrai code dans ce cas ?

struct POLICE{
  unsigned char hauteur;
  unsigned char largeur;
  unsigned char offset;
  const unsigned char* font; 
};

const unsigned char pMinus_5x3[3]={0x20,0x20,0x20};
const unsigned char p_5x3[3]={0x80,0,0};
const unsigned char slash_5x3[3]={0xC0,0x20,0x18};
const unsigned char p0_5x3[3]={0xF8,0x88,0xF8};
const unsigned char p1_5x3[3]={0xF8,0,0};
const unsigned char p2_5x3[3]={0xE8,0xA8,0xB8};
const unsigned char p3_5x3[3]={0x88,0xA8,0xF8};
const unsigned char p4_5x3[3]={0x38,0x20,0xF0};
const unsigned char p5_5x3[3]={0xB8,0xA8,0xE8};
const unsigned char p6_5x3[3]={0xF8,0xA8,0xE8};
const unsigned char p7_5x3[3]={0x08,0x28,0xF8};
const unsigned char p8_5x3[3]={0xF8,0xA8,0xF8};
const unsigned char p9_5x3[3]={0xB8,0xA8,0xF8};

const unsigned char pDeuxPoint_5x3[3]={0x50,0,0};

const unsigned char pRien1[3]={0x00,0x00,0x00};
const unsigned char pRien2[3]={0x00,0x00,0x00};
const unsigned char pRien3[3]={0x00,0x00,0x00};
const unsigned char pRien4[3]={0x00,0x00,0x00};
const unsigned char pRien5[3]={0x00,0x00,0x00};
const unsigned char pRien6[3]={0x00,0x00,0x00};

const unsigned char pA_5x3[3]={0xF0,0x28,0xF0};
const unsigned char pB_5x3[3]={0xF8,0xA8,0x50};
const unsigned char pC_5x3[3]={0x70,0x88,0x88};
const unsigned char pD_5x3[3]={0xF8,0x88,0x70};
const unsigned char pE_5x3[3]={0xF8,0xA8,0x88};
const unsigned char pF_5x3[3]={0xF8,0x28,0x08};
const unsigned char pG_5x3[3]={0x70,0x88,0xE8};
const unsigned char pH_5x3[3]={0xF8,0x20,0xF8};
const unsigned char pI_5x3[3]={0x88,0xF8,0x88};
const unsigned char pJ_5x3[3]={0xC0,0x80,0xF8};
const unsigned char pK_5x3[3]={0xF8,0x20,0xD8};
const unsigned char pL_5x3[3]={0xF8,0x80,0x80};
const unsigned char pM_5x3[3]={0xF8,0x10,0xF8};
const unsigned char pN_5x3[3]={0xF8,0x70,0xF8};
const unsigned char pO_5x3[3]={0xF8,0x88,0xF8};
const unsigned char pP_5x3[3]={0xF8,0x28,0x10};
const unsigned char pQ_5x3[3]={0xF8,0x48,0xB8};
const unsigned char pR_5x3[3]={0xF8,0x28,0xD0};
const unsigned char pS_5x3[3]={0xB8,0xA8,0xE8};
const unsigned char pT_5x3[3]={0x08,0xF8,0x08};
const unsigned char pU_5x3[3]={0xF8,0x80,0xF8};
const unsigned char pV_5x3[3]={0x38,0xC0,0x38};
const unsigned char pW_5x3[3]={0xF8,0x40,0xF8};
const unsigned char pX_5x3[3]={0xD8,0x20,0xD8};
const unsigned char pY_5x3[3]={0x18,0xE0,0x18};
const unsigned char pZ_5x3[3]={0xC8,0xA8,0x98};

const unsigned char pDegres_5x3[3]={0x10,0x40,0xA0};

const unsigned char* fontChiffre5x3[]={\
pMinus_5x3,p_5x3,slash_5x3,p0_5x3,p1_5x3,p2_5x3,p3_5x3,p4_5x3,p5_5x3,p6_5x3,\
p7_5x3,p8_5x3,p9_5x3,pDeuxPoint_5x3,pRien1,pRien2,pRien3,pRien4,pRien5,pRien6,\
pA_5x3,pB_5x3,pC_5x3,pD_5x3,pE_5x3,pF_5x3,pG_5x3,pH_5x3,pI_5x3,pJ_5x3,\
pK_5x3,pL_5x3,pM_5x3,pN_5x3,pO_5x3,pP_5x3,pQ_5x3,pR_5x3,pS_5x3,pT_5x3,\
pU_5x3,pV_5x3,pW_5x3,pX_5x3,pY_5x3,pZ_5x3,pDegres_5x3};

void setup(void)
{
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

POLICE font5x3 = {5,3,45,fontChiffre5x3[0]};

for(int i=0;i<140;i=i+3)
  {
  Serial.println(String(*(font5x3.font+i),HEX));
  }

}

void loop(void)
{}

En sortie, j’ai correctement le premier octet de chaque caractere.

Par contre, si je remplace les
“pRien1,pRien2,pRien3,pRien4,pRien5,pRien6,”

par
“pRien1,pRien1,pRien1,pRien1,pRien1,pRien1,”

ca ne marche plus, j’ai les premiers octets, puis un seul 0, et ca reprend normalement

Bonsoir,

Quand tu déclares :

const unsigned char* fontChiffre5x3[]= ...

fontChiffre5x3 est un const unsigned char**

Le membre font de ta struct est un unsigned char*

Quand tu lui affectes fontChiffre5x3[0], font pointe vers pMinus_5x3.

Ensuite dans ta boucles, via *(font5x3.font+i), tu accèdes successivement à 0x20 (le premier octet de pMinus_5x3 puis 3 octets plus loin dans une donnée qui dépend de l’allocation faite par le compilateur. Pour faire court, ça ne semble marcher que parce que ton tableau est initialisé exactement dans l’ordre de l’initialisation des variables qui le composent.
Il suffit que tu mettes autre chose dans ce tableau pour que ça ne marche plus.
Je ne penses pas que ce soit ça que tu veux.

1 - font doit être un unsigned char**
2 - il faut lui affecter fontChiffre5x3
3 - la boucle doit itérer de 1 en 1

Comme ceci :

struct POLICE{
  unsigned char hauteur;
  unsigned char largeur;
  unsigned char offset;
  const unsigned char** font; 
};

const unsigned char pMinus_5x3[3]={0x20,0x20,0x20};
const unsigned char p_5x3[3]={0x80,0,0};
const unsigned char slash_5x3[3]={0xC0,0x20,0x18};
const unsigned char p0_5x3[3]={0xF8,0x88,0xF8};
const unsigned char p1_5x3[3]={0xF8,0,0};
const unsigned char p2_5x3[3]={0xE8,0xA8,0xB8};
const unsigned char p3_5x3[3]={0x88,0xA8,0xF8};
const unsigned char p4_5x3[3]={0x38,0x20,0xF0};
const unsigned char p5_5x3[3]={0xB8,0xA8,0xE8};
const unsigned char p6_5x3[3]={0xF8,0xA8,0xE8};
const unsigned char p7_5x3[3]={0x08,0x28,0xF8};
const unsigned char p8_5x3[3]={0xF8,0xA8,0xF8};
const unsigned char p9_5x3[3]={0xB8,0xA8,0xF8};

const unsigned char pDeuxPoint_5x3[3]={0x50,0,0};

const unsigned char pRien[3]={0x00,0x00,0x00};

const unsigned char pA_5x3[3]={0xF0,0x28,0xF0};
const unsigned char pB_5x3[3]={0xF8,0xA8,0x50};
const unsigned char pC_5x3[3]={0x70,0x88,0x88};
const unsigned char pD_5x3[3]={0xF8,0x88,0x70};
const unsigned char pE_5x3[3]={0xF8,0xA8,0x88};
const unsigned char pF_5x3[3]={0xF8,0x28,0x08};
const unsigned char pG_5x3[3]={0x70,0x88,0xE8};
const unsigned char pH_5x3[3]={0xF8,0x20,0xF8};
const unsigned char pI_5x3[3]={0x88,0xF8,0x88};
const unsigned char pJ_5x3[3]={0xC0,0x80,0xF8};
const unsigned char pK_5x3[3]={0xF8,0x20,0xD8};
const unsigned char pL_5x3[3]={0xF8,0x80,0x80};
const unsigned char pM_5x3[3]={0xF8,0x10,0xF8};
const unsigned char pN_5x3[3]={0xF8,0x70,0xF8};
const unsigned char pO_5x3[3]={0xF8,0x88,0xF8};
const unsigned char pP_5x3[3]={0xF8,0x28,0x10};
const unsigned char pQ_5x3[3]={0xF8,0x48,0xB8};
const unsigned char pR_5x3[3]={0xF8,0x28,0xD0};
const unsigned char pS_5x3[3]={0xB8,0xA8,0xE8};
const unsigned char pT_5x3[3]={0x08,0xF8,0x08};
const unsigned char pU_5x3[3]={0xF8,0x80,0xF8};
const unsigned char pV_5x3[3]={0x38,0xC0,0x38};
const unsigned char pW_5x3[3]={0xF8,0x40,0xF8};
const unsigned char pX_5x3[3]={0xD8,0x20,0xD8};
const unsigned char pY_5x3[3]={0x18,0xE0,0x18};
const unsigned char pZ_5x3[3]={0xC8,0xA8,0x98};

const unsigned char pDegres_5x3[3]={0x10,0x40,0xA0};

const unsigned char* fontChiffre5x3[]={\
pMinus_5x3,p_5x3,slash_5x3,p0_5x3,p1_5x3,p2_5x3,p3_5x3,p4_5x3,p5_5x3,p6_5x3,\
p7_5x3,p8_5x3,p9_5x3,pDeuxPoint_5x3,pRien,pRien,pRien,pRien,pRien,pRien,\
pA_5x3,pB_5x3,pC_5x3,pD_5x3,pE_5x3,pF_5x3,pG_5x3,pH_5x3,pI_5x3,pJ_5x3,\
pK_5x3,pL_5x3,pM_5x3,pN_5x3,pO_5x3,pP_5x3,pQ_5x3,pR_5x3,pS_5x3,pT_5x3,\
pU_5x3,pV_5x3,pW_5x3,pX_5x3,pY_5x3,pZ_5x3,pDegres_5x3};

void setup(void)
{
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

POLICE font5x3 = {5,3,45,fontChiffre5x3};

for(int i=0;i<140;i++)
  {
  Serial.println(String(*(font5x3.font[i]),HEX));
  }

}

void loop(void)
{}

Ok,merci!
je vais regarder ca.
je vais surement devoir modifier ma fonction d’affichage suite à ca

Ah oui, je n'ai pas modifié la borne de ta boucle, 140, il faudrait que ça soit égal au nombre d'éléments de fontChiffre5x3

Je m’en doutais pour cette denriere correction.
Ent otu cas, merci,ca marche super. J’ai pigé mon erreur et donc je dois corriger tout ce qui en déoucle.
Par contre, si je veux atteindr ele deuxieme octet des caractèresje dois faire

  Serial.println(String(*(font5x3.font[i]+1),HEX));

?

Et en complément, j’ai une autre question lié aux pointeur.
J’ai un tableau à 2 dimension,et je veux le passer dans une fonction, pour ensuite balayer toutes les valeurs, est ce que faire ainsi ca fonctionne:

unsigned char tab[2][3];

void fonction(unsigned char * t)
{
   for(int i=0;i<2;i++)
   {
      for(int j=0;j<3;j++)
      {
        Serial.println(String(*t+(2*i)+j,HEX));
      }
   }
}

void setup(void)
{
Serial.begin(9600);

fonction(&tab[0][0]);
}

ou c’est encore une betise?
je penche pour la betise…

Bonsoir,

Hiko:
Par contre, si je veux atteindr ele deuxieme octet des caractèresje dois faire

  Serial.println(String(*(font5x3.font[i]+1),HEX));

?

Oui, ou plus lisiblement

  Serial.println(String(font5x3.font[i][1]),HEX));

Et en complément, j’ai une autre question lié aux pointeur.
J’ai un tableau à 2 dimension,et je veux le passer dans une fonction, pour ensuite balayer toutes les valeurs, est ce que faire ainsi ca fonctionne:

unsigned char tab[2][3];

void fonction(unsigned char * t)
{
   for(int i=0;i<2;i++)
   {
      for(int j=0;j<3;j++)
      {
       Serial.println(String(t+(2i)+j,HEX));
      }
   }
}

void setup(void)
{
Serial.begin(9600);

fonction(&tab[0][0]);
}




ou c'est encore une betise?
je penche pour la betise...

Sans essayer, je dirais que ça ne fonctionne pas.

t+(2i)+j déréférence t, on obtient donc le pointeur sur la ligne. Ensuite ajouter 2*i + j n’a pas trop de sens.

Il faut calculer l’adresse avant de déréférencer le pointeur. Comme la matrice a 3 colonne, i doit être multiplié par 3. L’expression est donc t + 3*i + j. Le tout est ensuite déréférencé :

(t + 3i + j)

Serial.println(String(*(t + 3*i + j),HEX));

Ok merci,mais je ne vais pas tomber sur le meme souci que précédement en fait. C'était surtout ca le but de ma question.

Faut vraiment que je commence à mieux comprendre les pointeurs moi...