Cosa stampa? (c++)

Sk_Anonymous
Ciao, potreste per favore dirmi cosa stampa la seconda riga di questo programma e perchè? In particolare non mi torna quel 150..

#include
using namespace std;
class c{
public:
double x,y;
c(double xx, double yy){
x=2*xx;
y=yy+1;
}
void f(int m){
x*=m;
y=x*m;
}
};
int main() {
c a(1,2), b(3,4);
b.f(5);
cout << a.x << " " << a.y << endl;
cout << b.x << " " << b.y << endl;
}

altro dubbio: qui il problema sono le ultime due righe..

#include
using namespace std;
class c{
public:
int x,y;
c() {
x=5; y=6;
}
void f1(int xx, int yy){
x=xx;
y=yy;
}
void f2(c &cc) {
x=2*cc.x;
y=cc.y+1;
cc.x+=2;
}
};
int main() {
c a, b;
cout << a.x << " " << a.y << endl;
a.f1(3,4);
cout << a.x << " " << a.y << endl;
b.f2(a);
cout << b.x << " " << b.y << endl;
cout << a.x << " " << a.y << endl;
}


Grazie

Risposte
apatriarca
Nel primo codice. b viene prima di tutto creato passando al costruttore $3$ e $4$. Le sue variabili membro saranno quindi inizializzate a $2 \times 3 = 6$ e $4 + 1 = 5$. Dopodiché viene chiamata la funzione $f$ che per prima cosa moltiplica $x$ per $m$ (e lo riscrive in $x$) e poi moltiplica nuovamente $x$ per $m$ e lo scrive in $y$. Per cui scrive $6 \times 5 = 30$ in $x$ e poi $30 \times 5 = 150$ in $y$ (ottenendo quindi il risultato che immagino tu abbia visto).

Nel secondo codice. $f1$ scrive semplicemente i valori che gli vengono passati nelle due variabili membro. Per cui dopo aver chiamato $f1$ dovremmo avere che a contiene $(3,4)$ mentre $b$ $(0,0)$. La funzione $f2$ modifica entrambe le classi. Prima scrive in $b.x \leftarrow 2 \times a.x = 2 \times 3 = 6$, poi scrive in $b.y \leftarrow a.y + 1 = 4 + 1 = 5$ e infine scrive in $a.x \leftarrow a.x + 2 = 3 + 2 = 5$. Nelle ultime due righe dovrebbe quindi stampare "6 5" e "5 4".

Sk_Anonymous
Grazie, sei stato gentilissimo!

avrei ancora una perplessita` su questo programma:
int f(int x, int &y, int *z){
if(x>=0) y++;
x=x+4;
for(int i=-1;i<x;i++)
z[i]+=3*i;
return y+4;
}

int main(){
int a=0,b=2,c[4]={1,2,3,4};
f(a,b,c+1);
cout<<a<<" "<<b<<" ";

Non capisco perche per b stampa 12. Non dovrebbe stampare 7? y viene inizializzato con 2, poi incrementa di 1 (y++), e poi la funzione deve restituirmi y+4, dunque ottengo 7, giusto?

vict85
ATTENZIONE: nel ciclo accedi a z[-1], che probabilmente nella tua esecuzione è y. È un errore grave e molto pericoloso, devi stare molto attento quando usi gli array.

In ogni caso nella riga "return y+4" y non viene modificato. Quindi il risultato dovrebbe essere 3 (mettendo a posto il ciclo).

Sk_Anonymous
Il testo del programma e' giusto: e' vero che accedo all'elemento z[-1], ma la variabile locale z e' inizializzata con l'argomento c+1. Quindi z[-1] diventa z[0], z[0] diventa z[1] e cosi' via. Ho avuto la svista di considerare y+4 come variazione di y , ma il programma continua a stamparmi 12 per la variabile b. E continuo a non capire il motivo.

vict85
Non lo avevo notato, una pratica comunque potenzialmente pericolosa, te lo sconsiglierei vivamente. Comunque è un esercizio e quindi non so quanto sia una tua scelta.
A me visual studio dà come risultato '0 3', conforme alle previsioni. Tu che usi?

P.S: comunque dovrebbe essere x = x +3, con 4 dovrebbe dare errori. A me visual studio fa comunque molte storie (a meno che non passi c e corregga dentro f in modo appropriato).

Sk_Anonymous
Uso Code Blocks, mi stampa sempre 12. A me torna 3, provo a vedere se risolvo.
Ciao, grazie

claudio862
x all'inizio vale 0 (il valore di a), viene incrementato di 4, quindi vale 4. Il ciclo for va da i = -1 ad i = x - 1 = 3. Ma z[3] equivale a c[4], che è fuori dall'array. Accedere ad un elemento oltre i limiti di un array è un comportamento indefinito, quindi può succedere qualsiasi cosa (in questo caso assegna 12 a y). Se il ciclo viene correttamente impostato for (int i = -1; i < x-1; ++i) da risultato 3.

Sk_Anonymous
"claudio86":
x all'inizio vale 0 (il valore di a), viene incrementato di 4, quindi vale 4. Il ciclo for va da i = -1 ad i = x - 1 = 3. Ma z[3] equivale a c[4], che è fuori dall'array. Accedere ad un elemento oltre i limiti di un array è un comportamento indefinito, quindi può succedere qualsiasi cosa (in questo caso assegna 12 a y). Se il ciclo viene correttamente impostato for (int i = -1; i < x-1; ++i) da risultato 3.


Sono delle osservazioni pertinenti. Non appena il testo dell'esame viene pubblicato sul sito posto il link, puo' darsi che abbia sbagliato qualcosa nel copiarlo sul foglio. E' possibile che i compilatori ci mettano del loro: sto usando la console di Linux Debian associata al programma Emacs come editor e non mi da nessun messaggio di errore.

claudio862
"saretta20":
E' possibile che i compilatori ci mettano del loro: sto usando la console di Linux Debian associata al programma Emacs come editor e non mi da nessun messaggio di errore.

Non è un errore, è un comportamento indefinito (che è molto peggio).
Per ogni istruzione ben definita il compilatore deve fare una delle due:
- Se l'istruzione è valida, generare il codice macchina corretto;
- Altrimenti fallire la compilazione (ed eventualmente mostrare un messaggio di errore).
In caso di comportamento indefinito invece ha la libertà di fare qualsiasi cosa. Potrebbe mostrare un errore e fallire la compilazione, oppure potrebbe generare del codice che fa quello che volevamo noi, oppure del codice che fa altro. La definizione che preferisco è dal (ottimo) libro Effective C++ di Scott Meyers:

"Scott Meyers":
it means it works during development, it works during testing, and it blows up in your most important customers' faces


Morale: il programma può essere completamente errato anche se il compilatore non mostra messaggi di errore.

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.