Pages: [1] 2   Go Down
Author Topic: Dubbio Puntatori-Variabili Globali  (Read 2261 times)
0 Members and 1 Guest are viewing this topic.
Rovereto
Offline Offline
Full Member
***
Karma: 5
Posts: 172
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Buongiorno a tutti!
Modificando il codice di uno sketch per gestire 3 linee di luci mi sono imbattuto nell'ancestrale dubbio sull'utilizzo dei puntatori.
Inizialmente globalmente venivano dichiarate 3 variabile distinte per le 3 linee di luci : (es. On1,On2,On3);
Per rendere tutto intuitivo e pratico ho deciso di sostituirle con degli array (es. On[2],Off[2] ...)

Il problema è che sostituendo i parametri nelle funzioni sembra che non sia possibile modificare le variabili globali negli array...
Prima le variabili venivano passate cosi...
Code:
byte On1, On2 On3;


void loop(){

funzione (&On1,&On2,&On3);
}

funzione (byte *O1, byte *O2, byte *O3){
O1=1;
O2=2;
O3=3;
}

Mente volevo modificarle in

Code:
byte On[2];

void loop(){
funzione (0);
}

funzione (byte n){
On[n]=1;
On[n+1]=2;
On[n+2]=3;
}

Tutti e due i metodi dovrebbero modificare le variabili a livello globale giusto?

è la stessa cosa che scrivere ?
Code:
byte On1, On2 On3;


void loop(){

funzione (On1,On2,On3);
}

funzione (byte &O1, byte &O2, byte &O3){
O1=1;
O2=2;
O3=3;
}

Spero di essermi spiegato bene.. perche nel caso degli array sembra non funzioni come dovrebbe: non modifica la variabile globalmente..
Buona giornata a tutti!

Logged

0
Offline Offline
Shannon Member
****
Karma: 131
Posts: 10473
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

esempio N°1 errato:
Quote
funzione (byte *O1, byte *O2, byte *O3){
O1=1;
O2=2;
O3=3;
}

così stai cambiando gli INDIRIZZI dei puntatori O1, O2 e O3 con i valori 1, 2 e 3. Tu vuoi cambiare i valori quindi ci va il * davanti (notare le parentesi, l'= ha prioristà rispetto a * !):
Quote
funzione (byte *O1, byte *O2, byte *O3){
(*O1)=1;
(*O2)=2;
(*O3)=3;
}


oppure, visto che array e puntatori sono la stessa cosa, puoi considerare il puntatore ad una variabile come un array di dimensione 1:

Quote
funzione (byte *O1, byte *O2, byte *O3){
O1[0]=1;
O2[0]=2;
O3[0]=3;
}

Quindi dire (*puntatore)=x o puntatore[0] = x è la stessa cosa!

invece il seguente che io sappia non ha senso, non dovrebbe nemmeno compilare:
Code:
funzione (byte &O1, byte &O2, byte &O3){
« Last Edit: February 27, 2013, 08:57:38 am by lesto » Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Ivrea
Offline Offline
God Member
*****
Karma: 5
Posts: 680
"La teoria è quando si sa tutto ma non funziona niente. La pratica è quando funziona tutto ma non si sa il perché. In ogni caso si finisce sempre con il coniugare la teoria con la pratica: non funziona niente e non si sa il perché." Albert Einstein
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Per prima cosa, essendo globali non importa che le passi come riferimento, funziona anche così:

Code:
byte On1, On2, On3;

void loop() {
  funzione ();
}

funzione () {
  O1=1;
  O2=2;
  O3=3;
}

Seconda cosa: quando definisci un array dentro le quadre devi mettere il numero di elementi, quindi variabile[3] sarà formata dagli elementi variabile[0], variabile[1], variabile[2]. Attenzione, nessuno ti vieta di andare a leggere/scrivere variabile[3] ma non sai cosa c'è, potresti fare danno (a livello software, chiaramente).

Terza cosa: il c++ tratta gli array come puntatori, quindi se crei un array variabile[3] lui ti crea un puntatore al primo elemento della lista. Per trovare un elemento della lista lui fa questa cosa:
variabile[2] = *(variabile+2)
A questo punto ti svelo un segreto del c++:
variabile[2] = *(variabile+2) = *(2+variabile) = 2[variabile]

E' un "baco" intrinseco del c++ per come tratta gli array...  smiley-wink
Logged

MC
Offline Offline
God Member
*****
Karma: 14
Posts: 917
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao,


Code:
funzione (byte &O1, byte &O2, byte &O3)


Cosa intenderesti fare con questa funzione ?
Se la tua idea era accettare dei parametri di tipo puntatore avresti dovuto mettere

Code:
funzione A(byte * O1, byte * O2, byte * O3)
{
// corpo della funzione
}

e chiamando quella funzione invece avresti dovuto mettere
Code:
A(&On1,&On2,&On3);

Perchè tutto ciò?

Semplice, nella firma della funzione specifici che il tipo di dato che passi, non èun byte, ma un puntatore ad un valore di quel tipo, e lo fai mettendo il simbolo *

Quando invece vai a richiamare quella funzione, devi indicare che non vuoi passare il valore della tua variabile On1,On2,On3 , ma bensi l'indirizzo di memoria in cui questa è stata allocata, pertanto devi mettere il simbolo &

In parole povere :

funzione A(byte * O1, byte * O2, byte * O3)
{
// corpo della funzione
}

significa che la tua funzione si aspetta di trovare 3 puntatori a byte come parametri (e attenzione poi a come li usi all'interno della funzione stessa!!)

e

 A(&On1,&on2,&On3)

equivale a : Chiama la funzione A passando L'INDIRIZZO DI MEMORIA di On1,L'INDIRIZZO DI MEMORIA di On2,L'INDIRIZZO DI MEMORIA di On3

Spero di averti chiarito.

Comunque il problema che lamenti per l'array globale non esiste, sicuramente hai fatto confusione .
Se passi alla funzione il puntatore corretto all'array, riesci tranquillamente a variarne il suo contenuto da qualsiasi parte del codice.




Logged

Vi è una spiegazione scientifica a tutto.
La fede è solo quell'anello che si porta al dito dopo il matrimonio.

0
Offline Offline
Shannon Member
****
Karma: 131
Posts: 10473
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Terza cosa: il c++ tratta gli array come puntatori, quindi se crei un array variabile[3] lui ti crea un puntatore al primo elemento della lista. Per trovare un elemento della lista lui fa questa cosa:
variabile[2] = *(variabile+2)
A questo punto ti svelo un segreto del c++:
variabile[2] = *(variabile+2) = *(2+variabile) = 2[variabile]

E' un "baco" intrinseco del c++ per come tratta gli array...  smiley-wink

non ho capito la storia del baco, puoi spiegare meglio?

comuqnue che io sappia:
variabile[2] = *(variabile+2*sizeof(tipoDell'array))

dove sizeof è la dimensione in byte della variabile float (4 byte nei sistemi 32bit, 8byte nei 64bit, ecco perchè inviare un float grezzo da arduino ad un PC 64bit può essere più problematico del previsto smiley )

importante perchè dando ad un array void non puoi usare [] (alcune implementazioni puoi e ti muovi di un byte), o puoi leggere un array di float byte per byte invece che float per float cambiando semplicemente il tipo di puntatore all'array...

per spiegarmi:
Code:
float n = 12.3;
byte *p;
p = &n; //ora P punta all'area di memoria di n
for (int i=0; i<sizeof(float); i++){
   Serial.print("byte: ");
   Serial.print(i);
   Serial.print(" = ");
   Serial.println(p[i], BIN);
}
« Last Edit: February 27, 2013, 09:03:58 am by lesto » Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Ivrea
Offline Offline
God Member
*****
Karma: 5
Posts: 680
"La teoria è quando si sa tutto ma non funziona niente. La pratica è quando funziona tutto ma non si sa il perché. In ogni caso si finisce sempre con il coniugare la teoria con la pratica: non funziona niente e non si sa il perché." Albert Einstein
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

non ho capito la storia del baco, puoi spiegare meglio?

Prova a eseguire questo codice:

Code:
int variabile[3] = {55, 46, 19};

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

void loop() {
  Serial.println(variabile[1],DEC);
  Serial.println(1[variabile],DEC);
  delay(1000);
}

EDIT
Ho modificato il codice, diciamo che ero stato un po troppo precipitoso nello scriverlo... =)
« Last Edit: February 27, 2013, 09:17:33 am by Janos » Logged

0
Offline Offline
Shannon Member
****
Karma: 131
Posts: 10473
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
Serial.println(variabile[1],DEC);
  Serial.println(1[variabile],DEC);

ad occhio direi che dimostra che la chiamata sizeof() non viene fatta come dico io esplicitamente ma viene fatta all'interno dell'operatore +:

indirizzo di variabile = 100
print1 = 100+1int (cioè 2 byte) = 102
print2 = 1int(cioè 2 byte) +100 = 102

con la sizeof esplicita:
print1 = 100+ 1*sizeof(int)= 102
print2 = 1 +100*sizeof(int *) = 201
(tutti i puntatori sono di 2 byte!, ma in realtà fa una sizeof di variabile... se variabile è stato dicjhiarato come array, allora ritorna il numero dei suoi elementi (3 nel nostro caso), se invece è un puntatore all'array, oppure l'array è stato passato ricevuto come parametro (quindi in realtà è stato di nascosto trasformato in puntatore) ritorna sempre la dimensione dell'area di memoria del puntatore, che è 2byte (forse 4 nei 64bit) )
« Last Edit: February 27, 2013, 09:38:34 am by lesto » Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

ivrea (to)
Offline Offline
Faraday Member
**
Karma: 87
Posts: 4956
miaaao ^-^
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Perchè non dovrebbe funzionare ? Arduino non è standard C++?
Code:
byte On1, On2 On3;
void loop()
{ funzione (On1,On2,On3);
}

funzione (byte &p1, byte &p2, byte &p3)
{
}

Questo è "Passaggio di parametri per riferimento"
http://www.html.it/pag/15499/parametri-per-valore-o-per-riferimento/
Logged

my name is IGOR, not AIGOR

0
Offline Offline
Shannon Member
****
Karma: 131
Posts: 10473
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

no, arduino usa il Wiring, che è in pratica C con un pizzico di C++..
e non conoscevo questa semplificazione del C++, c'è da vedere se arduino la supporta.

Quindi il primo sistema corretto è identico al terzo
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Ivrea
Offline Offline
God Member
*****
Karma: 5
Posts: 680
"La teoria è quando si sa tutto ma non funziona niente. La pratica è quando funziona tutto ma non si sa il perché. In ogni caso si finisce sempre con il coniugare la teoria con la pratica: non funziona niente e non si sa il perché." Albert Einstein
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Wiring non è un linguaggio di programmazione, Arduino si programma in C++ al quale è stato aggiunto il framework Wiring, ovvero una serie di funzioni/librerie/API per semplificare la vita al programmatore. Wiring è un framework, non un linguaggio............

e non conoscevo questa semplificazione del C++, c'è da vedere se arduino la supporta.

A quale ti riferisci? A quella dell'esempio che ho postato io?
Logged

0
Offline Offline
Shannon Member
****
Karma: 131
Posts: 10473
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

quella della & per ricevere puntatori al posto del *

Quote
Arduino si programma in C++
Hai ragione ho controllato, la il punto è che è un C++ castrato, la prova è che negli IDE < 1.0 non esisteva nemmeno l'operatore new e delete.
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 332
Posts: 22811
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

quella della & per ricevere puntatori al posto del *

Quote
Arduino si programma in C++
Hai ragione ho controllato, la il punto è che è un C++ castrato, la prova è che negli IDE < 1.0 non esisteva nemmeno l'operatore new e delete.
Questi sono stati introdotti nella versione 1.0.3, ne detti notizia io qualche settimana fa ricordi?
Logged


Rovereto
Offline Offline
Full Member
***
Karma: 5
Posts: 172
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ma quindi a parte l'errore che ho fatto di digitazione nella prima le 3 forme sono uguali?

Code:
byte On1, On2 On3;
void loop()
{ funzione (On1,On2,On3);
}

funzione (byte &p1, byte &p2, byte &p3)
{
}

Che io sappia questa forma è propria del C++ (non c'è nel C) come dice nid69ita
ho provato ad utilizzarla e "sembra" funzionare... qualcuno però mi può confermare che funzioni come dovrebbe?
Logged

0
Offline Offline
Shannon Member
****
Karma: 131
Posts: 10473
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

sì, non ricordavo la versione precisa ed ho generalizzato.
Il punto è che bisogna fare mooolta attenzione a dire che è C++, io direi che
Quote
è in pratica C con un pizzico di C++..

Quote
Ma quindi a parte l'errore che ho fatto di digitazione nella prima le 3 forme sono uguali?
bhe la seconda usa un array che ha vantaggi e svantaggi ma in linea di massima sì, sono equivalenti

Quote
Che io sappia questa forma è propria del C++ (non c'è nel C) come dice nid69ita
esatto, se compila funziona, vai tranquillo
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Ivrea
Offline Offline
God Member
*****
Karma: 5
Posts: 680
"La teoria è quando si sa tutto ma non funziona niente. La pratica è quando funziona tutto ma non si sa il perché. In ogni caso si finisce sempre con il coniugare la teoria con la pratica: non funziona niente e non si sa il perché." Albert Einstein
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quello che hai fatto è passare alla funzione dei parametri come riferimento:

http://www.html.it/pag/15499/parametri-per-valore-o-per-riferimento/

Il che è tanto corretto quanto inutile. Come ti ho già detto sopra, quelle variabili sono definite globali e quindi visibili in tutto il programma. Se fai diventare il tuo codice così:

Code:
byte On1, On2 On3;
void loop()
{ funzione ();
}

funzione ()
{
}

Funziona alla stessa maniera. Ti consiglio di dare un'occhiata a questo link, che fra l'altro spiega anche il tempo di vita delle stesse...

http://webuser.unicas.it/tortorella/FondInf_0809/PDF/10-visibilita%20variabili.pdf
Logged

Pages: [1] 2   Go Up
Jump to: