[RISOLOTO] Restituire una struct da una funzione

dopo aver letto struct e funzioni - Italiano - Arduino Forum ma.... non ho capito come utilizzarle ... il valore restituito è sempre

Ora(h:m:s:): : :

All'interno della funzione è tutto OK

Non riesco a capire cosa sbaglio :frowning:

Grazie

...cut...
struct posizione
 {
     char ore;
     char minuti;
     char secondi;
 } ;


posizione ORA;


void loop() 
{
...cut...

      ORA=ConvertiMinuti(TempoS);
      Serial.print("Ora(h:m:s:): ");
      Serial.print(ORA.ore);
      Serial.print(":");
      Serial.print(ORA.minuti);
      Serial.print(":");
      Serial.println(ORA.secondi);
      Serial.println("---------------------------");
...cut...
  
}



posizione ConvertiMinuti(float Temp){

posizione pos;

...cut...

 return(pos);

}

Se dichiari posizione pos; all'interno della funzione ... come esci con il return pos viene distrutto ed il pointer non è più valido.

Metti la dichiarazione di pos fuori della funzione (globale) e vedi se va ...

Guglielmo

Grazie provato ma non funziona ... Anche se viene distrutto fuori dalla funzione ma ... prima dovrebbe restituire la struttura?

ALT....

ho cambiato la struttura in

struct posizione
 {
     int ore;
     int minuti;
     int secondi;
 } ;

così funziona... ciò mi sebra strano anche dovrei capire meglio il cast di arduino anche perchè in C

c=(int)(365.25*anno);

se c vale 735978.4567... restituise 735978.000000 mentre arduino restituisce 32767

siccome all'interno della funzione calcolaminuti faccio dei cast in int mi sa che il problema è proprio quello ... il cast in char non funziona...

grazie

Guarda che l'int di Arduino è di due byte quindi +32767 .. -32768.

In ogni caso, i valori di ritorno NON è bene che siano dichiarati dinamicamente dentro la funzione (variabili che vengono rilasciate al momento dell'uscita) ... ti può andare bene e ti può andare male; ad esempio, con gli array di char (stringhe) ... va quasi sempre male :smiley:

Guglielmo

Vero... mia svista tra int ....

dichiarerò global il valore di ritorno ...

grazie 1000 mi sono perso in un bicchiere d'acqua ... dopo circa 10 anni che non programmo ... :o

Nota che se lo dichiari global manco serve ritornarlo :).

grazie però la devo richiamare su 4 strutture diverse
2 su scala temporale e 2 su scala angolare

Grazie ancora ... un'ultima cosa per avere il valore intero della variabile in C di solito utilizzo (int) ma ho notato che qui non posso causa dimensione ristretta ... forse (long) ?

Se è globale è globale, è accessibile da ovunque anche senza restituirla.

Un'alternativa è passare la struttura da riempire come parametro della funzione, come puntatore o reference. In questo modo è un po' più pulito.

int è un intero a 16 bit su Arduino, se ti servono interi più grandi usa pure long, che è composto da 32 bit, come normalmente gli int su PC.

Ok grazie :slight_smile:

così funziona e a parte qualche mio strafalcione serale e di arrugginimento .... comunque meglio...

...cut...

struct posizione
 {
     int ore;
     int minuti;
     int secondi;
 } ;


posizione ORA;


void loop() 
...cut...

      Serial.print("Tempo(decimali): ");
      Serial.println(TempoS,7);
      ConvertiMinuti(TempoS,&ORA);
      Serial.print("Ora(h:m:s:): ");
      Serial.print(ORA.ore);
      Serial.print(":");
      Serial.print(ORA.minuti);
      Serial.print(":");
      Serial.println(ORA.secondi);
      Serial.println("---------------------------");

  
}



void ConvertiMinuti(float Temp,posizione *pos ){


...cut...


}

La struttura e qualunque altro tipo puoi dichiararlo locale (quindi dentro una funzione) e poi restituirne il valore tramite return var;

Prima di distruggere la variabile ne viene fatta copia ed è questa che viene resistuita, le cose non stanno proprio cosi, ma non c'è rischio nel restituire una variabile locale.

Il problema si presenta invece restituendo un puntatore a dato locale, il quale viene distrutto e il puntatore restituito punta a nulla.

Ciao.

MauroTec:
La struttura e qualunque altro tipo puoi dichiararlo locale (quindi dentro una funzione) e poi restituirne il valore tramite return var;

Io non ho provato, ne sei sicuro ? Non usa un puntatore ?

MauroTec:
Il problema si presenta invece restituendo un puntatore a dato locale, il quale viene distrutto e il puntatore restituito punta a nulla.

Esatto, infatti con un byte/int/long funziona, ma per evitare problemi ... preferisco sempre dire di non farlo :wink: ...

Comunque, se si vuole dichiarare la variabile (di qualunque tipo) all'interno della funzione, basta dichiararla static ... così sopravvive e non c'è problema :wink:

Guglielmo

gpb01:
Io non ho provato, ne sei sicuro ? Non usa un puntatore ?

Si, funziona con i compilatori C. A meno che il gcc, che viene chiamato da Arduino IDE, non "castri" qualcosa con qualche parametro. Ma questo esempio a me funziona:

struct MyStr { int i; };
struct MyStr f(struct MyStr p)
{  struct MyStr r = p;
  return r;
}
void setup() 
{ Serial.begin(9600);
}
void loop() 
{ struct MyStr x = { 12 };
  struct MyStr y = f(x);
  Serial.println(y.i);
}

Le strutture dovrebbero essere passate per valore come i tipi base del linguaggio (a quel che ricordo).
Nei libri infatti si suggerisce di usare i puntatori soprattutto se le struct sono "grosse", visto che un passaggio per valore implica anche delle copie "nascoste".

Se non ricordo male la struct con dentro una stringa è un trucco "sporco" per passare una stringa o array per copia ad una funzione. Logicamente se l'array è grosso... è una cosa da fessi.

Ricordo anche che la parola struct prima del nuovo "tipo" dichiarato è obbligatorio.
Questo non è valido: posizione ORA;
Questo si: struct posizione ORA;

Meglio usare un typedef:

typedef struct sPosiz
 { int ore, minuti, secondi;
 } Posizione;
Posizione MyPos;

nid69ita:
Ricordo anche che la parola struct prima del nuovo "tipo" dichiarato è obbligatorio.
Questo non è valido: posizione ORA;
Questo si: struct posizione ORA;

Meglio usare un typedef:

typedef struct sPosiz[color=#222222][/color]

{ int ore, minuti, secondi;
} Posizione;
Posizione MyPos;

Quello che dici è vero in C, ma in C++ struct è praticamente un sinonimo di class (con la differenza che ha visibilità pubblica di default), per cui non serve il typedef e si può dichiarare una variabile (= un oggetto) senza metterci struct davanti.

Se non ricordo male la struct con dentro una stringa è un trucco "sporco" per passare una stringa o array per copia ad una funzione.

mmmm...a rigor di logica la cosa equivale a restituire un puntatore ad array locale non statico.
I registri interni dell'atmega non sono infiniti quindi per forza di cose le dichiarazioni locali finiscono nello stack.
Per ospitare un array dentro una struttura il membro deve essere di tipo puntatore.
Quando dichiari locale la variabile di tipo struct nello stack ci finisce l'array, quando restituisci la variabile per valore, viene fatta copia del puntatore, che però punta ad una porzione di memoria stack non più valida.

Mentre se l'array è dichiarato globale o static o dinamicamente la cosa deve funzionare. Se globale o static (di modulo o di funzione) il puntatore ad array punta ad un indirizzo stabilito a compile-time, se allocata dinamicamente il puntatore punta ad un indirizzo stabilito a run-time.

Quello che dici è vero in C, ma in C++ struct è praticamente un sinonimo di class (con la differenza che ha visibilità pubblica di default), per cui non serve il typedef e si può dichiarare una variabile (= un oggetto) senza metterci struct davanti.

Si si, proprio così, non lo dimentichiamo il compilatore invocato da Arduino è avr-cpp( preprocessore ) avr-g++ (compilatore) ed avr-ld come linker.

class in più ha anche, costruttori, distruttori, costruttori di copia e tante altre cose che provocano un gran mal di testa. :angry:

Ciao.

MauroTec:
class in più ha anche, costruttori, distruttori, costruttori di copia e tante altre cose che provocano un gran mal di testa. :angry:

Tutto questo lo puoi mettere anche in una struct. Davvero, struct == class, cambia solo la visibilità data di default ai membri, che è private per class e public per struct.

Tutto questo lo puoi mettere anche in una struct. Davvero, struct == class, cambia solo la visibilità data di default ai membri, che è private per class e public per struct.

Pure, non lo sapevo, quindi anche overload degli operatori?
Si ma il distruttore di struct come si fa?

Porca paletta, ho un solo cervello e tutto dentro non ci sta. :slightly_frowning_face:

Ciao.

È più semplice di quel che pensi :). In sostanza, scrivere:

struct Antani {
  ...
};

È equivalente a scrivere:

class Antani {
public:
  ...
};

Dove al posto dei puntini puoi scrivere tutto quel che vuoi, allo stesso modo!