Pages: [1]   Go Down
Author Topic: sizeof d'un tableau de byte faux dans une fonction  (Read 1267 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour

Je débute avec Arduino, et je souhaite créer une fonction "debug" qui me permette d'afficher le contenu d'un tableau de byte de façon lisible dans la console (Serial).
Exemple: 90, E6, BA, BC, 99, 2A

Pour tester, je déclare un tableau de taille 6, et quand je fais un sizeof dessus ça me retourne bien 6.
Maintenant quand je passe ce tableau à une fonction, et que que je fais un sizeof sur le paramètre, ça m'affiche 2 :

Code:
byte monTableau[] = { 0x90, 0xE6, 0xBA, 0xBC, 0x99, 0x2A };

void setup() {
  Serial.begin(9600);
  Serial.println(sizeof(monTableau)); // affiche 6
  debug(monTableau);
}

void loop() {
  
}

// Ma fonction pour afficher un tableau :
void debug(byte* data){
  Serial.println(sizeof(data)); // affiche 2, WTF ?
  for(int i=0; i<sizeof(data); i++){
    if(i>0){
      Serial.print(", ");
    }
    Serial.print(data[i], HEX);
  }
  Serial.println("");
}

J'ai cherché un peu, et j'ai vu que sizeof était évalué au moment de la compilation, et pas de l’exécution, du coup il me retourne la taille du pointeur (2), et pas celle du tableau smiley-eek.

Est-ce qu'il y a un moyen pour calculer la taille du tableau passé en paramètre de ma fonction debug ?
Sinon il me reste plus qu'à ajouter un paramètre size à ma fonction, mais ça sera moins pratique à utiliser...

Merci
Logged


France
Offline Offline
Faraday Member
**
Karma: 52
Posts: 5341
Arduino Hacker
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour,

J'ai cherché un peu, et j'ai vu que sizeof était évalué au moment de la compilation, et pas de l’exécution, du coup il me retourne la taille du pointeur (2), et pas celle du tableau smiley-eek.
sizeof est une instruction évalué uniquement à la compilation.
La valeur de sizeof est remplacé par la taille statique de l'objet passé en argument.
Faire une sizeof sur quelque chose de dynamique donnera uniquement la taille du pointeur qui lui correspond.

Est-ce qu'il y a un moyen pour calculer la taille du tableau passé en paramètre de ma fonction debug ?
Sinon il me reste plus qu'à ajouter un paramètre size à ma fonction, mais ça sera moins pratique à utiliser...
Réponse bête et méchante : NON.
En c/c++ il n'y as pas de gestion des buffer overflow (enfin si dans certain cas, mais pas ici) comme c'est le cas dans certain autre langage (python, java, ...).
Il n'y a donc pas de moyen de savoir combien fait un tableau en taille (chaine de caractéres exclu, puisse qu'elle sont censé se finir par \0).

De même c'est une des raisons qui fait que :
Code:
byte t[5];
t[10] = 42;
Ne génère pas d'erreur lors de la compilation, mais fait n'importe quoi lors de l'exécution.
(Dans ce cas précis ou t[10] est demandé implicitement il y aurait eu un warning, mais si t[10] avait était remplacé par t[a] avec a=10 il n'y aurait pas eu de warning)
Logged

Des news, des tuto et plein de bonne chose sur http://skyduino.wordpress.com !

Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, merci beaucoup pour cette réponse claire & complète.
Logged


La Roche sur Yon - France
Offline Offline
Newbie
*
Karma: 0
Posts: 32
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour,

Sauf erreur de ma part, tu dois pouvoir faire ça
Code:
Serial.println(sizeof(data)); // affiche 2, WTF ?
Serial.println(sizeof(&data)); // affiche 6, normalement ?

le & permet de cibler la variable pointée par le pointeur.

A tester
Logged

Arduino Mega 2560 R2
Shield Ethernet + SD
Arduino 1.0

Ile-de-France (92 sud), France
Offline Offline
Edison Member
*
Karma: 23
Posts: 2054
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Non

si data est déclaré comme dans le code ci-dessus :
Code:
void debug(byte* data)
data est donc une variable pointeur sur octet.

Alors:
sizeof( data ) = taille d'un pointeur = 2 sur Arduino
sizeof( &data ) = taille d'un pointeur sur un pointeur = taille d'un pointeur = toujours 2
sizeof( *data ) = taille de 1 élement du type pointé par un pointeur = sizeof (byte) = 1

Le seul moyen de faire une fonction générique d'affichage comme le demande Galdon est de passer la taille à l'exécution.
Par exemple :
Code:
void debug(byte* data, size_t len)

A utiliser par
Soit :
Quote
char  Tableau[15];
debug( Tableau, sizeof(Tableau) );
Soit :
Quote
#define DATA_SIZE  15
char *Tableau= malloc( DATA_SIZE );
debug( Tableau, DATA_SIZE );  // car sizeof(Tableau)==2 et sizeof(*Tableau)==1
Éventuellement si on sait qu'il s'agit d'une chaîne de caractères terminée par un caractère nul '\0' on peu utiliser strlen().

Mais en C/C++, dès qu'on passe par des pointeurs on ne sait plus combien d'objets sont pointés.
Logged

Barbuduino: Arduino sur Breadboard & VinciDuino: Clone Leonardo // WR703: Mini-routeur hacké // LauchPad MSP430 et Stellaris // Panda II Arduino-like .NetMF sous VisualC#
RTFC: Read That F.....g Code / RTFD: Read That F.....g Doc / RTFDS: Read That F.....g DataSheet / RTFS: Read That F.....g Schematic / Wot da ya wanna D.I.Y. today ?

Offline Offline
Full Member
***
Karma: 0
Posts: 224
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
#define DATA_SIZE  15
char *Tableau= malloc( DATA_SIZE );
debug( Tableau, DATA_SIZE );  // car sizeof(Tableau)==2 et sizeof(*Tableau)==1

Ne pas oublier de libérer la mémoire après smiley-wink
Code:
free(Tableau);
Logged


La Roche sur Yon - France
Offline Offline
Newbie
*
Karma: 0
Posts: 32
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OK.  smiley-roll
Au temps pour moi.
Logged

Arduino Mega 2560 R2
Shield Ethernet + SD
Arduino 1.0

France
Offline Offline
Faraday Member
**
Karma: 52
Posts: 5341
Arduino Hacker
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
#define DATA_SIZE  15
char *Tableau= malloc( DATA_SIZE );
debug( Tableau, DATA_SIZE );  // car sizeof(Tableau)==2 et sizeof(*Tableau)==1
Éventuellement si on sait qu'il s'agit d'une chaîne de caractères terminée par un caractère nul '\0' on peu utiliser strlen().
Il faut éviter au maximum de faire des malloc() quand on a que 2Ko de RAM ... un malloc ça passe, deux malloc sa fragmente, trois malloc tu sait plus ou tu en est ...
Quitte à allouer une taille fixe de char autant faire une variable "normal" telle que : char Tableau[DATA_SIZE] ...

Sinon il reste la solution de la macro pré-processeur ?
Genre :
Code:
#define debug(data) { \
  Serial.println(sizeof(data)); \
  for(uint8_t i=0; i < sizeof(data); ++i) { \
    if(i) Serial.print(", "); \
    Serial.print(data[i], HEX); \
  } \
  Serial.println(); \
}
Par contre ça va ajouter du code à chaque fois que debug(...) sera utilisé, dans certain cas ça peut rendre le code hyper lourd une fois compilé.
Mais il y un gros avantage, une fois la phase de debug finit il suffit de faire #define debug(data) {} et hop ! Plus rien !
Logged

Des news, des tuto et plein de bonne chose sur http://skyduino.wordpress.com !

Pages: [1]   Go Up
Jump to: