Sizeof con gli array

Salve, mi dite come funziona sizeof con gli array? Ho fatto delle prove ma dai risultati non ho capto come funziona. In questo sketch mi esce sempre zero, invece dovrebbe dirmi da quanti elementi è formato l'array.

void draw_menu(String disegna_menu[]) {
  int num_ele = sizeof(disegna_menu)/sizeof(disegna_menu[0]);
  Serial.print(num_ele);
 for (int i = 0; i < num_ele; i++) { // per ogni elemento del menù
   if (i == riga) { // se è l'elemento selezionato
     ucg.setColor(1,0, 0, 255); // sfondo blu
    } else { // altrimenti
     ucg.setColor(1,0, 0, 0); // sfondo nero
    }
   ucg.setPrintPos(115 -i*20, 10); // posiziono il cursore sul display
   ucg.print(disegna_menu[i]); // stampo il nome dell'elemento
  } 
}

devi passare l'elemento count come parametro alla funzione. una volta che sei nella funzione è troppo tardi.

cerca il decadimento nella conversione da array a puntatore ( decay in array -to-pointer conversion)

sizeof con gli array di String

Mi sa che sizeof() non funziona con gli oggetti String! infatti esiste length():

l'utilizzo di sizeof per contare il numero di elementi in un array funzionerebbe correttamente con quel codice indipendentemente dal tipo di elementi.

il problema qui è che quando passi un array come parametro passi solo il puntatore al primo elemento e la dimensione viene persa. questo è ciò che riguarda il decadimento.

basta aggiungere il conteggio come parametro e usarlo nella funzione

Il problema è che li NON sta passando un "char array", ma, peggio, sta passano un oggetto della classe "String"!

Come ha fatto giustamente notare Datman, per determinare la lunghezza di un oggeto della classe "String" c'è un apposito metodo di detta classe, il metodo length().

Guglielmo

@arturo2222 non vuole la lunghezza di una String ma il numero di elementi nell'array passato come parametro

questo non funziona (decay)

@J-M-L: ... ok ... vero, non avevo notato le due parentesi quadre dopo disegna_menu[] ... :roll_eyes: quindi, lui passa un array di oggetti String e vuole sapere quanti elementi ha tale array ... in tal caso, il solo modo è passare un parametro in più con il numero di elementi.

Guglielmo

:slight_smile:
oppure utilizzare un template ma non sono molto favorevole a questa soluzione

se il codice è in esecuzione su un Arduino a 32 bit, potrebbe essere utilizzato un diverso tipo di contenitore (vector, ...) e passato per riferimento e la dimensione non andrebbe persa

1 Like

Ne avevamo già discusso in passato circa i template, ma non ricordo dove, cercherò. Perché non sei favorevole? c'è qualche side effect che non ho considerato in passato. Io ricordo che era equivalente a passare due argomenti.

Trovato il thread

Ciao.

se chiami la funzione con - diciamo 10 array di dimensioni diverse, il codice della funzione viene duplicato 10 volte...

C'è un modo per aggirare questo: il template chiama una funzione che prende la dimensione come parametro, quindi ottieni meno duplicazioni di codice, ma se ti preoccupi di scrivere tu stesso quella funzione con il parametro dimensione, puoi semplicemente usarlo direttamente.

Altrimenti, nel caso specifico, basta impostare num_ele con un numero massimo di elementi ammessi.
Forse, poi, c'è anche qualche maniera completamente diversa e più semplice per colorare la riga desiderata...

e fare un:

for(String a:b){
    conta_elementi += 1;
}

PS:...aspetta lui passa l'array...devo provare...

non funzionerà perché una volta passato l'array alla funzione, non è più un array , è un puntatore all'inizio dell'array. (decadimento del puntatore). Quindi otterrai un errore durante la compilazione perché non puoi ottenere un iteratore (begin) per il puntatore.

String menuA[] = {"menuA1", "menuA2", "menuA3", "menuA4", "menuA5"};
String menuB[] = {"menuB1", "menuB2"};

void printMenuBuono(String mioMenu[], size_t conta_elementi) {
  for (size_t i = 0; i < conta_elementi; i++)
    Serial.println(mioMenu[i]);
}

void printMenuErrato(String mioMenu[]) {
  size_t conta_elementi = sizeof mioMenu / sizeof * mioMenu; // <=== errore (decadimento del puntatore) --> 2 / 6 = 0
  Serial.print(F("sizeof mioMenu=")); Serial.println(sizeof mioMenu);
  Serial.print(F("sizeof * mioMenu=")); Serial.println(sizeof * mioMenu);
  Serial.print(F("conta_elementi=")); Serial.println(conta_elementi);

  for (size_t i = 0; i < conta_elementi; i++)
    Serial.println(mioMenu[i]);
}

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

  // Buono
  Serial.println(F("------------------"));
  printMenuBuono(menuA, sizeof menuA / sizeof * menuA);
  Serial.println(F("------------------"));
  printMenuBuono(menuB, sizeof menuB / sizeof * menuB);
  Serial.println(F("------------------"));

  // Codice errato
  Serial.println(F("------------------"));
  printMenuErrato(menuA);
  Serial.println(F("------------------"));
  printMenuErrato(menuB);
  Serial.println(F("------------------"));



}

void loop() {}

Cosa succede però se la lunghezza degli item di menuA è variabile?
Secondo me sarebbe preferibile definire la dimensione dell'array a priori magari con un #define

un Array ha una dimensione fissa, il numero massimo di elementi che può memorizzare è noto. Non può crescere né restringersi.

Se non lo riempi, invece di passare il numero massimo, passi un altro numero che corrisponde al numero effettivo di elementi attivi nell'array. ➜ sei responsabile di non passare un valore maggiore della dimensione dell'array

All'inizio avevo creato questa routine passando due elementi, l'array e il numero degli elementi, mi funzionava. Poi navigando in rete mi sono imbattuto nel comando sizeof e così ho pensato di mandare solo l'array e calcolarmi il numero degli elementi in automatico. La stessa formula, nel corpo del programma mi restituisce il numero degli elementi esatti.

Puoi anche contare gli elementi e passare il valore alla funzione...

➜ …

Perché nel corpo del programma stai usando l'array stesso e non un suo puntatore.
Come ti ha già spiegato @J-M-L è un fenomeno noto nel C: se fai una ricerca con le parole chiave "array to pointer decay", troverai molte informazioni al riguardo.

Io invece vorrei suggerire un approccio diverso al tuo problema. Se ho ben capito, l'array dovrà contenere le voci di un menù che con tutta probabilità saranno immutabili nel corso dell'esecuzione del programma.
Io non sono un NO-String a prescindere, ma usare un array di String in questo caso comporta un inutile spreco di SRAM.
Fossi in te userei dei const char* salvando l'array nel program space usando la keyword PROGMEM.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.