Go Down

Topic: Passaggio di argomenti ad una funzione (Read 1 time) previous topic - next topic

cyberhs

Aug 04, 2012, 08:14 pm Last Edit: Aug 04, 2012, 08:20 pm by cyberhs Reason: 1
Probabilmente per un esperto è una sciocchezza, ma non ho capito bene come passare gli argomenti ad una funzione.

Mi spiego meglio: dovrei passare una variabile ad una funzione, senza conoscere a priori che tipo è (byte, int, long, float, char, String).

La funzione lavora sulla rappresentazione della variabile in memoria, cioé sul puntatore della stessa.

Ho provato, ma ovviamente mi da un errore in compilazione sulla riga di invocazione.

Dove sbaglio?

Code: [Select]

  long Long = 250000;


  EEPROMVarSave(0x0400, Long);
...
void EEPROMVarSave(unsigned long Address, int *Var) {

 byte WBuffer;
 byte Size = sizeof(Var);

 for (byte I = 0; I < Size; I ++) {
   WBuffer = *((byte*)&Var + I);
   EEPROM.write(Address + I, WBuffer);
 }
}


ale92

è tardi quindi magari non sto pensando correttamente...ma se ricordo bene il puntatore deve essere dello stesso tipo della variabile puntata (pensando al motivo mi viene in mente il fatto che quando vai a dereferenziare il puntatore deve sapere quanti byte leggere tipo int 4 byte oppure long 8 byte...<-- ragionamento fatto ora non so quanto possa essere valido)
quindi in questo caso ti dà errore per 2 motivi, il primo è che la variabile è long, e l'altro è perchè in realtà non stai passando alla funzione un puntatore ma una variabile per passare un puntatore hai 2 modi o fai una variabile puntatore che punta a Long di questo tipo
Code: [Select]

int* punt = Long;

e poi alla funzione passi punt e non Long, oppure altro metodo che ha lo stesso risultato è usare i riferimenti mettendo una & davanti alla variabile che passi e quindi diventa &Long  (i riferimenti sono un altro modo di dire "l'indirizzo di Long")

PaoloP

Se non erro non è possibile passare un parametro ad una funzione senza stabilirne il tipo.
Pero puoi crearti tante funzioni identiche che accettino in ingresso tipi diversi, è poi il compilatore che in base al tipo decide quale funzione usare.

void Stampa(char input)....
void Stampa(int input)...
void Stampa(char input)...

--> http://it.wikipedia.org/wiki/Overloading

cyberhs

Per Ale92

Grazie della risposta... assonnata! :-)

Per PaoloP:

hum... questi spiegherebbe perché la funzione print(x) della Serial è composta in realtà da tante funzioni quante sono le possibi tipologie di variabile.

Però mi sembra proprio incredibile che non si possa...

m_ri

hai diverse strade:
-gli passi DUE argomenti: il primo,è un puntatore a void,nel secondo specifichi il tipo di argomento,usando Xes un'enumerazione(se gli passi 1,intendi int,2=stringa....)..quando richiami la funzione,scrivi per esempio   funzionePippo((void*)nomeVariabile,1)..all'interno della variabile,avrai uno switch case per tutti i possibili tipi di dato su v+cui vuoi lavorare...
-usi i template di c++
-usi binding dinamico,ma ho i miei dubbi sul fatto che l'arduino lo regga,mentre le prime due strade possono essere mooolto efficienti se implementate bene..

poi ci sono molte altre strade,che posso elencarti,ma con una delle prime due dovresti cavartela egregiamente..
tieni comunque conto che la funzione chiamata dovrà conoscere il tipo,o quando viene compliata,o quando viene richiamata..

cyberhs

Caro m_ri,

tu parti dal presupposto che io conosca bene il C, ma purtroppo non è cosi. :-(

Potresti gentilmente modificare la routine che ho postato all'inizio e che funziona ma che non riesco a richiamare?

Grazie infinite!

Ettore Massimo Albani

m_ri

vabbò,col primo metodo:

Code: [Select]

enum{ intero,stringa}tipoArg;

void EEPROMVarSave(unsigned long Address, void *Var,tipoArg tipo) {

switch(tipo){
case intero:
  byte WBuffer;
  byte Size = sizeof(Var);

  for (byte I = 0; I < Size; I ++) {
    WBuffer = *((byte*)&Var + I);
    EEPROM.write(Address + I, WBuffer);
break;
case stringa:
for (byte I = 0;; I ++) {
    WBuffer = *((byte*)(Var + I));
    EEPROM.write(Address + I, WBuffer);
    if(WBuffer==0)break;//esco dal ciclo dopo aver salvato il carattere 0
  }
break;
}
}

probab ci sono errori di sintassi..

cunctator

#7
Aug 06, 2012, 01:16 am Last Edit: Aug 07, 2012, 03:56 am by cunctator Reason: 1
Questo e' con i template, a mio parere la scelta migliore nel tuo caso ( Arduino ci va a nozze e tu non ti devi sbattere sul codice ;) ):
Code: [Select]

void EPROOM_write( unsigned addr , void* buff , unsigne length )
{
unsigned i;
while( length - i++ ) EPROOM.write( ((unsigned char*)addr) + i , buff[i] );
}

template <class type> void EPROOM_write( unsigned addr , type var )
{
EEPROM.write( addr , &var , sizeof(type) );
}

void EPROOM_write( unsigned addr , const char* str )
{
do EEPROM.write( addr++ , *str ); while( *str++ ); // oppure EEPROM.write( addr , str , strlen( str ) + 1 );
}


Ci sarebbe anche un'altra via, che non necessita di g++ ma si basa sul precompilatore, in pratica il risultato e' lo stesso dei template, ma se vuoi del codice C99 "pulito" ti puo' aiutare, probabilmente e' inutilmente macchinoso nel tuo caso, ma hai detto mai:
Code: [Select]

void EPROOM_write_ptr( unsigned addr , void* buff , unsigne length )
{
unsigned i;
while( length - i++ ) EPROOM.write( ((unsigned char*)addr) + i , buff[i] );
}

#define EPROOM_write( TYPE , ADDR , VAR ) EPROOM_write_ ## TYPE ( unsigned ADDR , VAR )

#define EPROOM_WRITE( TYPE ) void EPROOM_write_ ## TYPE ( unsigned addr , TYPE var ) \
{ \
EEPROM_write_ptr( addr , &var , sizeof(type) ); \
}
EPROOM_WRITE( unsigned char )
EPROOM_WRITE( unsigned short )
...
EPROOM_WRITE( signed short )
EPROOM_WRITE( signed long )

void foo()
{
EPROOM_write( unsigned int , 0xDEADBEAF, 12345 );
EPROOM_write( signed car , 0xABCDEFAB, 0x7F );
...
}


Good luck!

Go Up