Passaggio dei Parametri
Linguaggio: C++
Tema: Passaggio dei Parametri per Valore/Riferimento (Reference)
Nota: Sono alle primissime armi.
Ho questo (facile) programma:
void increment (int& i)
{
++i;
}
int main()
{
int j = 5;
increment (j);
std::cout << j << "\n";
return 0;
}
OUTPUT: 6
Il motivo di questo output è che si inizializza la variabile i di tipo reference della funzione con l'INDIRIZZO della variabile j. Quindi i e j appartengono alla stessa locazione di memoria, quindi hanno lo stesso valore 5. La funzione incrementa di 1 la variabile i (quindi j) e otteniamo come OUTPUT 6. (Eventuali correzioni alle mie motivazioni sono gradite!)
DOMANDA 1: se volessi avere come OUTPUT anche il valore della variabile i come faccio? L'OUTPUT sarà 6. Ho provato così:
ovviamente si aggiunge l'istruzione (std::cout << i ) però devo anche dichiarare la variabile i in MAIN, quindi (int i; ).
Ho provato a compilare però mi dice che devo inizializzare la variabile i, ma se la inizializzo - NON SO PERCHÉ - mi dà il valore inizializzato e non il valore 6. Cosa devo fare?
DOMANDA 2: volevo vedere la DIFFERENZA omettendo l'operatore & nell'argomento formale della funzione.
L'Output per la variabile j sarà 5, e non più 6. Infatti omettendo l'operatore & in questo caso è come se non ci fosse nemmeno la funzione (per lo meno per la variabile j). In questo caso si inizializza la variabile i (argomento della funzione) con il valore della variabile j (quindi 5). La funzione incrementa di 1 il valore della variabile i e quindi sarà 6 (per la variabile i). (Come sempre, eventuali correzioni sono gradite!)
Inoltre - come nella DOMANDA 1 - vorrei sapere come fare per far uscire l'OUTPUT della variabile i (visto che mi dà i soliti problemi che ho espresso sopra).
Avrei finito. Grazie a chi ha pazienza per rispondere. Cmq sia ho cercato di dare delle mie motivazioni, forse anche giuste.
Ciao.
Tema: Passaggio dei Parametri per Valore/Riferimento (Reference)
Nota: Sono alle primissime armi.
Ho questo (facile) programma:
void increment (int& i)
{
++i;
}
int main()
{
int j = 5;
increment (j);
std::cout << j << "\n";
return 0;
}
OUTPUT: 6
Il motivo di questo output è che si inizializza la variabile i di tipo reference della funzione con l'INDIRIZZO della variabile j. Quindi i e j appartengono alla stessa locazione di memoria, quindi hanno lo stesso valore 5. La funzione incrementa di 1 la variabile i (quindi j) e otteniamo come OUTPUT 6. (Eventuali correzioni alle mie motivazioni sono gradite!)
DOMANDA 1: se volessi avere come OUTPUT anche il valore della variabile i come faccio? L'OUTPUT sarà 6. Ho provato così:
ovviamente si aggiunge l'istruzione (std::cout << i ) però devo anche dichiarare la variabile i in MAIN, quindi (int i; ).
Ho provato a compilare però mi dice che devo inizializzare la variabile i, ma se la inizializzo - NON SO PERCHÉ - mi dà il valore inizializzato e non il valore 6. Cosa devo fare?
DOMANDA 2: volevo vedere la DIFFERENZA omettendo l'operatore & nell'argomento formale della funzione.
L'Output per la variabile j sarà 5, e non più 6. Infatti omettendo l'operatore & in questo caso è come se non ci fosse nemmeno la funzione (per lo meno per la variabile j). In questo caso si inizializza la variabile i (argomento della funzione) con il valore della variabile j (quindi 5). La funzione incrementa di 1 il valore della variabile i e quindi sarà 6 (per la variabile i). (Come sempre, eventuali correzioni sono gradite!)
Inoltre - come nella DOMANDA 1 - vorrei sapere come fare per far uscire l'OUTPUT della variabile i (visto che mi dà i soliti problemi che ho espresso sopra).
Avrei finito. Grazie a chi ha pazienza per rispondere. Cmq sia ho cercato di dare delle mie motivazioni, forse anche giuste.
Ciao.
Risposte
Il linguaggio C è classificato come linguaggio di alto livello (HLL, High Level Language). In realtà è uno dei più vicini in assoluto alla macchina, molto più di linguaggi nati anche molti anni prima (es. COBOL).
In altri termini, C somiglia più ad un macroassemblatore che ad un vero e proprio linguaggio di alto livello, ossia ad un linguaggio con costrutti e sintassi tipicamente orientati all'utente ed al dominio del problema.
Tuttavia, una delle caratteristiche che lo rendono HLL e lo differenziano dai classici assembler è proprio lo scope, ossia la visibilità limitata delle variabili utilizzate, che di fatto esiste solamente (entro certi limiti: local labels etc.) in alcuni sofisticati macroassembler relativamente recenti. Questo è anche il primo prerequisito per poter pensare di implementare il criterio di information hiding di Parnas.
In C, referenziare una variabile all'esterno del suo intervallo di validità sintattico provoca gli errori dei quali hai già fatto tuo malgrado la conoscenza. Senza complicare troppo la trattazione, diciamo che le cose stanno così anche nel linguaggio C++, che deriva dal C e lo estende.
Per definizione, lo scope di una variabile è limitato alla coppia di parentesi graffe che ne racchiudono la dichiarazione più da vicino.
Variabili dichiarate al di fuori di qualsiasi blocco sintattico sono visibili all'intero file sorgente (modulo), ed anche oltre con banali accorgimenti (es. la keyword extern). Ma non divaghiamo.
A questo punto, tornando al tuo esempio, dovrebbe essere chiaro che potrai stampare il valore della tua variabile i solo ed esclusivamente entro la funzione ove essa ha validità, ossia entro la increment() e non altrove, poiché al di fuori di quella coppia di parentesi non è accessibile alcuna "i".
Tutto chiaro ? Pensa sempre in termini di confini determinati dal blocco sintattico (= coppia di parentesi) ove viene dichiarata la variabile.
EDIT: typos
In altri termini, C somiglia più ad un macroassemblatore che ad un vero e proprio linguaggio di alto livello, ossia ad un linguaggio con costrutti e sintassi tipicamente orientati all'utente ed al dominio del problema.
Tuttavia, una delle caratteristiche che lo rendono HLL e lo differenziano dai classici assembler è proprio lo scope, ossia la visibilità limitata delle variabili utilizzate, che di fatto esiste solamente (entro certi limiti: local labels etc.) in alcuni sofisticati macroassembler relativamente recenti. Questo è anche il primo prerequisito per poter pensare di implementare il criterio di information hiding di Parnas.
In C, referenziare una variabile all'esterno del suo intervallo di validità sintattico provoca gli errori dei quali hai già fatto tuo malgrado la conoscenza. Senza complicare troppo la trattazione, diciamo che le cose stanno così anche nel linguaggio C++, che deriva dal C e lo estende.
Per definizione, lo scope di una variabile è limitato alla coppia di parentesi graffe che ne racchiudono la dichiarazione più da vicino.
Variabili dichiarate al di fuori di qualsiasi blocco sintattico sono visibili all'intero file sorgente (modulo), ed anche oltre con banali accorgimenti (es. la keyword extern). Ma non divaghiamo.
int Global1 = 0; /* Questa variabile è valida in tutto il sorgente, accessibile da qualsiasi funzione */ void fun1(int p1) { /* Le seguenti variabili "esistono" solo fino alla prossima parentesi graffa chiusa */ int a, b; a = p1; b = 2 * a; printf("a = %d, b = %d\n", a, b); } int main(void) { /* a è visibile solo nel main ! Non si sovrappone ad altre variabili col medesimo nome dichiarate privatamente ad altri blocchi */ int a; int j; /* Idem come sopra */ a = 99; fun1(a); for (j = 0; j < 10; ++j) { int a; /* Perversione ! Ma non sovrascrive l'altra a dichiarata a monte */ a = j * 3; printf("a = %d\n", a); } printf("a = %d\n", a); return(0); }
A questo punto, tornando al tuo esempio, dovrebbe essere chiaro che potrai stampare il valore della tua variabile i solo ed esclusivamente entro la funzione ove essa ha validità, ossia entro la increment() e non altrove, poiché al di fuori di quella coppia di parentesi non è accessibile alcuna "i".
Tutto chiaro ? Pensa sempre in termini di confini determinati dal blocco sintattico (= coppia di parentesi) ove viene dichiarata la variabile.
EDIT: typos
Grazie per la disponibilità e per la tua esposizione.
Effettivamente bastava mettere nel corpo della funzione l'istruzione (std::cout << i ) e non in MAIN come facevo io.
Mi interessava anche sapere se le mie motivazioni circa l'uso dell'operatore & fossero corrette visto che sono le prime volte che lo utilizzo, ma se non hai detto nulla al riguardo dovrebbero essere a posto. E questo mi rende felice.
Grazie. Ciao.
Effettivamente bastava mettere nel corpo della funzione l'istruzione (std::cout << i ) e non in MAIN come facevo io.
Mi interessava anche sapere se le mie motivazioni circa l'uso dell'operatore & fossero corrette visto che sono le prime volte che lo utilizzo, ma se non hai detto nulla al riguardo dovrebbero essere a posto. E questo mi rende felice.
Grazie. Ciao.
Ciao,
sebbene io abbia capito (io credo) un'istruzione del tipo:
int& j = i;
o funzioni contenenti parametri di tipo reference come:
void (int& i) {
++i;
}
NON ho capito quando l'operatore & è associato ad una funzione come:
int& funzione_bella (int .......) {
...
return .....
}
Purtroppo non ho un esempio concreto nel materiale didattico di studio e quindi chiedo se qualcuno ha un esempio molto semplice con relativa spiegazione per capire l'uso dell'operatore & associato ad una funzione.
Posso ipotizzare che il return (che sarà di tipo reference) sia un lvalue, ma il resto non lo ho compreso.
Grazie a chi risponde. Ciao.
sebbene io abbia capito (io credo) un'istruzione del tipo:
int& j = i;
o funzioni contenenti parametri di tipo reference come:
void (int& i) {
++i;
}
NON ho capito quando l'operatore & è associato ad una funzione come:
int& funzione_bella (int .......) {
...
return .....
}
Purtroppo non ho un esempio concreto nel materiale didattico di studio e quindi chiedo se qualcuno ha un esempio molto semplice con relativa spiegazione per capire l'uso dell'operatore & associato ad una funzione.
Posso ipotizzare che il return (che sarà di tipo reference) sia un lvalue, ma il resto non lo ho compreso.
Grazie a chi risponde. Ciao.
Esatto l'oggetto ritornato può essere assegnato. Di solito questa caratteristica si usa però in C++ per le classi per fare i metodi di tipo assegnamento. In C non mi viene in mente un esempio in cui questo possa avere particolare senso, dato che ritornare una referenza a un oggetto che poi viene distrutto alla fine dell'esecuzione della funzione non mi sembra una gran buona idea. Comunque volendo si può fare. Ti allego un esempio che è in C++ solo perché non mi ricordo più i printf... 
l'output del programma sarà:
a testimonianza che tutto funziona come uno può congetturare...

#include<iostream> using namespace std; int value=0; int & funzione() { return value; } int main() { cout << value << endl; funzione()=3; cout << value << endl; }
l'output del programma sarà:
0 3
a testimonianza che tutto funziona come uno può congetturare...