View Full Version : [Linguaggi] Dubbi su pre e post incremento (decremento),lvalue ed rvalue
Ciao a tutti. Devo sostenere Linguaggi 1, sul mio libro non riesco a trovare esempi e neppure su internet. Ho solo esercizi del prof. con i risultati, senza spiegazione. Spero mi possiate aiutare o indirizzare verso qualche buon testo. Si parla in generale di linguaggi C-like.
Qualcosa di semplice:
x = 3; z = 2;
x += z++;
dovrebbe essere equivalente a scrivere:
x = x + z;
z = z + 1;
Se c'è un array di mezzo, Cosa succede?
foo(a[i++]);
equivale a:
foo(a[i]);
i = i + 1;
cioè quando ritorna foo(), allora i viene incrementato. Quindi se accedo a i, ad esempio nel corpo di foo(), il valore è da considerarsi senza incremento?
Ultimo caso. Se ho una chiamata a funzione:
v = 3;
G(v-- + R(v))
dove R è un'altra funzione, come viene valutato ciò che è dentro G? Viene chiamato G(3 + R(2)), o G(3 + R(3)) e al ritorno della chiamata viene decrementato v?
chiedo veramente un aiuto, un tutorial, altrimenti potrei impazzire (già studiare il 5 agosto...:doh: ). E pensare che credevo di conoscere il linguaggi :)
Ciao
x = 3; z = 2;
x += z++;
dovrebbe essere equivalente a scrivere:
x = x + z;
z = z + 1;
mi sembra corretto
foo(a[i++]);
equivale a:
foo(a[i]);
i = i + 1;
mi sembra corretto
v = 3;
G(v-- + R(v))
questo è il più interessante. sono abbastanza sicuro che in C e C++ il comportamento del compilatore sia indefinito.
EDIT: guarda se questo ti può interessare:
http://www.embedded.com/story/OEG20020429S0037
ciao!
british
Energy++
05-08-2009, 20:32
cioè quando ritorna foo(), allora i viene incrementato. Quindi se accedo a i, ad esempio nel corpo di foo(), il valore è da considerarsi senza incremento?
prima di tutto nella funzione foo() non hai accesso alla i, ma solo al valore i-esimo dell'array che viene passato come argomento e poi:
se i = 10
foo(a[i++); equivale a foo(a[10]);
la i viene incrementata solo dopo aver effettuato la chiamata alla funzione.
[CODE]
v = 3;
G(v-- + R(v))
questo è il più interessante. sono abbastanza sicuro che in C e C++ il comportamento del compilatore sia indefinito.
british
Non è indefinito, è sugli esercizi del professore. Cmq leggendo velocemente l'articolo che mi hai linkato, mi è venuto in mente che è specificato, nell'esercizio, ordine di valutazione degli argomenti da sinistra a destra. Quindi quale sarebbe l'invocazione corretta?
cioè quando ritorna foo(), allora i viene incrementato. Quindi se accedo a i, ad esempio nel corpo di foo(), il valore è da considerarsi senza incremento?
prima di tutto nella funzione foo() non hai accesso alla i, ma solo al valore i-esimo dell'array che viene passato come argomento e poi:
se i = 10
foo(a[i++); equivale a foo(a[10]);
la i viene incrementata solo dopo aver effettuato la chiamata alla funzione.
Se consideri questi blocchi (anche senza l'array):
{
i= 1;
void foo(by value int x) {
x = 4; // non serve a nulla
stampa(i);
}
foo(i++);
}
EDIT:
quindi i viene incrementata subito dopo la chiamata (quando ENTRO in foo()), o quando la chiamata ritorna?
banryu79
06-08-2009, 08:39
Se consideri questi blocchi (anche senza l'array):
{
i= 1;
void foo(by value int x) {
x = 4; // non serve a nulla
stampa(i);
}
foo(i++);
}
EDIT:
quindi i viene incrementata subito dopo la chiamata (quando ENTRO in foo()), o quando la chiamata ritorna?
Ma non puoi scrivere del codice che ti stampi a video il valore di 'i' subito prima della chiamata, all'inizio dell'esecuzione del corpo della funzione 'foo' e subito dopo che la funzione è tornata?
Lo mandi in esecuzione e ti togli il dubbio :)
Comunque, se non erro, la definizione degli operatori di pre e post incremento è ben definita:
++(expression)
L'operatore di pre-incremento aggiunge 1 a expression e restituisce il risultato.
expression++
L'operatore di post-incremento aggiunge 1 a expression e restituisce il valore iniziale di expression (il valore prima dell'addizione).
Percui nel tuo esempio che ho quotato la variabile 'i', inizializzata al valore 1, quando viene passata per copia del valore alla invocazione della funzione 'foo', la copia passata vale ancora 1 (in quanto è il valore di ritorno dell'operatore di post-incremento e di conseguenza il parametro formale 'x' dentro lo scope di 'foo' vale 1) mentre la variabile 'i' vale 2.
Kralizek
06-08-2009, 09:11
v = 3;
G(v-- + R(v))
questo è il più interessante. sono abbastanza sicuro che in C e C++ il comportamento del compilatore sia indefinito.
Io propendo per
G(3 + R(2))
astorcas
06-08-2009, 09:22
Io propendo per
G(3 + R(2))
quoto
Io propendo per
G(3 + R(2))
Io per G(3 + R(3)) . MINGW32
Edit:
Nel C l'ordine di valutazione degli operandi di un qualsiasi operatore non e' conosciuto a priori (ad eccezione degli operatori '&&', '||' '?:' e ','). Questo significa che data l'espressione a = f1() + f2(), non e' possibile sapere a priori se verra' valutata prima la funzione f1() e poi la funzione f2() o viceversa. Pertanto se la funzione f1() altera il valore di una variabile utilizzata dall'altra funzione f2() o viceversa, il risultato dipendera' dall'ordine di valutazione delle due funzioni. Non e' conosciuto a priori nemmeno l'ordine di valutazione degli argomenti passati ad una funzione, pertanto una chiamata a funzione del tipo: 'funz(a, ++a)' produce un risultato dipendente dall'implementazione del compilatore usato. Situazione analoga si puo' avere in una chiamata a funzione del tipo: 'funz (funz2(a) - funz2(b))' se il valore ritornato da funz2() puo' risultare diverso tra la prima e la seconda chiamata
http://www.wowarea.com/italiano/linux/linguaggioc06.htm
yorkeiser
06-08-2009, 10:30
Su Code::Blocks (quindi compilatore mingw):
G(3+R(3))
Sarei curioso di provarla sul cl microsoft, ma non ce l'ho installato qui.
Io ho provato a fare il programma:
#include <iostream>
using namespace std;
void G(int arg)
{
cout << "G: v-- + R(v): " << arg <<"\n";
}
int R(int arg)
{
cout << "R: v= " << arg<<"\n";
return arg;
}
int main()
{
int v=3;
G(v-- + R(v));
cout << "v: " << v;
cout << "\n";
return 0;
}
E questo è l'output.. forse è un po arzigogolato ma spero si capisca lo stesso :stordita::
R: v= 3
G: v-- + R(v): 6
v: 2
EDIT: code::blocks su windows
astorcas
06-08-2009, 10:33
Su Code::Blocks (quindi compilatore mingw):
G(3+R(3))
Sarei curioso di provarla sul cl microsoft, ma non ce l'ho installato qui.
vs 2005, c#, G(3 + R(2))
Sarei curioso di provarla sul cl microsoft, ma non ce l'ho installato qui.
a me su VS 2008, quindi visual C++, da lo stesso output del mio post precedente.
banryu79
06-08-2009, 10:39
Minchia, è partita l'investigazione di massa :D
yorkeiser
06-08-2009, 10:43
vs 2005, c#, G(3 + R(2))
Java 6 concorda.
Attendiamo cdimauro per il pitone :)
astorcas
06-08-2009, 10:47
a me su VS 2008, quindi visual C++, da lo stesso output del mio post precedente.
public class Program
{
static void Main(string[] args)
{
int v = 3;
G(v--, R(v));
Console.Read();
}
static int R(int j)
{
Console.WriteLine("R: a = {0}", j);
return j;
}
static int G(int a, int b)
{
Console.WriteLine("G: a = {0} b = {1}, a+b = {2}", a, b, a + b);
return a + b;
}
}
}
Output:
R: a = 2
G: a = 3 b = 2, a+b = 5
malocchio
06-08-2009, 10:49
Ovvero, comportamento indefinito per C/C++ (dipende dal compilatore...)?
[cut]
ma questo è C# o sbaglio?
yorkeiser
06-08-2009, 10:52
Ovvero, comportamento indefinito per C/C++ (dipende dal compilatore...)?
Propendo per il sì, bisognerebbe però provare con altri compilatori c (non c#)
EDIT: ho visto ora il post di xblitz, per ora in entrambi i casi (mingw e cl microsoft) viene valutata come g(3+r(3))
astorcas
06-08-2009, 10:54
ma questo è C# o sbaglio?
si si io infatti facevo la mia parte col c#, non dovevo? :fagiano:
EDIT: a me cmq sembra che tutti quelli che hanno fatto prove col c++ hanno avuto lo stesso risultato, ossia diverso da tutti gli altri linguaggi :)
Kralizek
06-08-2009, 11:00
questo topic é la cosa piú vicina alle pippazze mentali che abbia mai visto! :P
si si io infatti facevo la mia parte col c#, non dovevo? :fagiano:
Perchè? anzi, personalmente sarei proprio curioso di vedere come si comportano i vari linguaggi...
astorcas
06-08-2009, 11:03
questo topic é la cosa piú vicina alle pippazze mentali che abbia mai visto! :P
sapessi quante pippe mi faccio! :asd: (mentali)
malocchio
06-08-2009, 11:07
questo topic é la cosa piú vicina alle pippazze mentali che abbia mai visto! :P
Stavo giusto per DISiscrivermi...
Però mi sembra importante sapere che non si può contare su queste cose. Magari uno non ci pensa e arriva a dover debuggare per capire cosa non va.
astorcas
06-08-2009, 11:37
Java 6 concorda.
Attendiamo cdimauro per il pitone :)
se non sbaglio il pitone non ha gli operatori di incremento/decremento
marko.fatto
06-08-2009, 11:40
Ruby non li ha..
banryu79
06-08-2009, 11:42
Stavo giusto per DISiscrivermi...
Però mi sembra importante sapere che non si può contare su queste cose. Magari uno non ci pensa e arriva a dover debuggare per capire cosa non va.
Sì però se uno arriva a scrivere una roba del genere:
...
int result = functionCall(a++, a, 2*a--, eChiPiùNeHaPiùNeMetta...);
...
è giusto che soffra come un cane dei bug più rognosi e bastardi che gli possano capitare nella sua esperienza di programmazione, e che il compilatore gli esploda sotto il sedere :asd:
yorkeiser
06-08-2009, 11:42
se non sbaglio il pitone non ha gli operatori di incremento/decremento
Mmmh da una googlata veloce vedo che hai ragione... scelta curiosa.
malocchio
06-08-2009, 12:02
se non sbaglio il pitone non ha gli operatori di incremento/decrementoRuby non li ha..http://digilander.libero.it/arosati76/Noname.gif
Sì però se uno arriva a scrivere una roba del genere:
...
int result = functionCall(a++, a, 2*a--, eChiPiùNeHaPiùNeMetta...);
...
è giusto che soffra come un cane dei bug più rognosi e bastardi che gli possano capitare nella sua esperienza di programmazione, e che il compilatore gli esploda sotto il sedere :asd:
Eddai se non si fanno robe del genere che divertimento c'è? :asd:
goldorak
06-08-2009, 13:54
Ultimo caso. Se ho una chiamata a funzione:
v = 3;
G(v-- + R(v))
dove R è un'altra funzione, come viene valutato ciò che è dentro G? Viene chiamato G(3 + R(2)), o G(3 + R(3)) e al ritorno della chiamata viene decrementato v?
chiedo veramente un aiuto, un tutorial, altrimenti potrei impazzire (già studiare il 5 agosto...:doh: ). E pensare che credevo di conoscere il linguaggi :)
Ciao
G(3+R(3)) ed il motivo e' semplice.
Benche' il C non garantisca l'ordine in cui vengono valutate le espressioni, in questo caso non incide per niente.
Per semplicita' considera l'espressione X = v-- + R(v) e fai la chiamata G(X).
Ora indipendentemente che R(v) vengano valutato prima di v-- o dopo e supponendo che R(v) non abbia effetti collaterali su v, il valore dell'espressione e cioe' il valore assegnato a X sara' sempre X = 3 + R(3) e subito dopo v varra' 2. Quindi G sara' chiamato con il valore 3+R(3).
astorcas
06-08-2009, 14:00
G(3+R(3)) ed il motivo e' semplice.
Benche' il C non garantisca l'ordine in cui vengono valutate le espressioni, in questo caso non incide per niente.
Per semplicita' considera l'espressione X = v-- + R(v) e fai la chiamata G(X).
Ora indipendentemente che R(v) vengano valutato prima di v-- o dopo e supponendo che R(v) non abbia effetti collaterali su v, il valore dell'espressione e cioe' il valore assegnato a X sara' sempre X = 3 + R(3) e subito dopo v varra' 2. Quindi G sara' chiamato con il valore 3+R(3).
Scusa ma non ho capito la semplicità di tale motivo...
v--+R(v) non è un'espressione atomica, quindi l'ordine in cui vengono eseguite le due espressioni è importante e come!
goldorak
06-08-2009, 14:09
Scusa ma non ho capito la semplicità di tale motivo...
v--+R(v) non è un'espressione atomica, quindi l'ordine in cui vengono eseguite le due espressioni è importante e come!
Non ho detto che l'ordine delle espressioni non e' importante, tanto e' vero che il C appunto non garantisce che R(v) venga valutato prima di v--.
Ma in questo caso il valore dell'espressione e' 3 + R(3) perche' l'operatore di decremento postfisso garantisce che il valore della variable v verra' decrementata soltanto dopo che l'espressione totale sara' stata valutata. E secondo te con quale valore viene valutata ? Con 3.
malocchio
06-08-2009, 14:17
Ma in questo caso il valore dell'espressione e' 3 + R(3) perche' l'operatore di decremento postfisso garantisce che il valore della variable v verra' decrementata soltanto dopo che l'espressione totale sara' stata valutata. E secondo te con quale valore viene valutata ? Con 3.
Come fai a sapere che è così e non è perché viene valutata prima R(v) e dopo v-- , avendo come espressione risultato sempre 3+R(3), o meglio R(3)+3?? :confused:
astorcas
06-08-2009, 14:19
Non ho detto che l'ordine delle espressioni non e' importante, tanto e' vero che il C appunto non garantisce che R(v) venga valutato prima di v--.
Ma in questo caso il valore dell'espressione e' 3 + R(3) perche' l'operatore di decremento postfisso garantisce che il valore della variable v verra' decrementata soltanto dopo che l'espressione totale sara' stata valutata. E secondo te con quale valore viene valutata ? Con 3.
Ok ora capisco meglio quello che dici, però la cosa sembra aver subito interpretazioni differenti a seconda del linguaggio. In C in effetti il comportamento è quello che dici, ma in altri linguaggi, (C# e Java testati) al momento della chiamata di R, v vale già 2.
ok, è chiaro il post di goldorak, quindi in questo caso l'ordine di valutazione (sx->dx o il contrario) non è importante, quindi posto scrivere:
v = 3;
G(v-- + R(v));
equivale a:
v = 3;
x = v-- + R(v);
G(x); // chiamato con 3 + R(3)
v = v - 1;
allora quando risulterebbe importante l'ordine di valutazione? e se fosse stato --v + R(v)??
goldorak
06-08-2009, 14:40
Ok ora capisco meglio quello che dici, però la cosa sembra aver subito interpretazioni differenti a seconda del linguaggio. In C in effetti il comportamento è quello che dici, ma in altri linguaggi, (C# e Java testati) al momento della chiamata di R, v vale già 2.
Il comportamente dipende sia dal linguaggio che dal compilatore.
goldorak
06-08-2009, 14:47
allora quando risulterebbe importante l'ordine di valutazione? e se fosse stato --v + R(v)??
Mhm cerchero' di essere piu' chiaro. Il problema si presenta sia con --v che con v++.
Il C come linguaggio non garantisce che R(v) verra' valutato prima di v--,v++,etc... E ci sono dei casi appunto come quello sopraelencato in cui --v+R(v) non e' uguale a R(v)+ --v. Detto questo, alcuni compilatori prendono delle decisioni "arbitrarie" nel senso
di valutare sempre i termini da sinistra a destra e quindi una espressione come --v + R(v) avra' sempre un valore ben definito che sara' diverso da R(v) + --v. Ma questo dipende dall'implementazione, ed in questo senso non bisognerebbe mai fare affidamento su calcoli il cui valore dipende dall'ordine di valutazione di una espressione.
Quindi per rispondere in maniera definitiva al tuo primo post, il valore di G(v--+R(v)) dipende dall'implementazione del linguaggio.
Varia caso per caso.
ok, è chiaro il post di goldorak, quindi in questo caso l'ordine di valutazione (sx->dx o il contrario) non è importante, quindi posto scrivere:
v = 3;
G(v-- + R(v));
equivale a:
v = 3;
x = v-- + R(v);
G(x); // chiamato con 3 + R(3)
v = v - 1;
allora quando risulterebbe importante l'ordine di valutazione? e se fosse stato --v + R(v)??
v viene decrementato di 1 prima di essere valutato quindi: 2+R(2) e qui *credo* che tutti i linguaggi si comportino allo stesso modo...
malocchio
06-08-2009, 15:10
Ma l'ordine di valutazione non è definito né nella valutazione di un'espressione aritmetica, né nella valutazione di una lista di argomenti per la chiamata di una funzione...
marko.fatto
06-08-2009, 15:14
@malocchio: come mai così tanto stupore? :fagiano:
credevo di aver capito, ma il seguente piccolo esercizio (scope statico) mi ha rispedito in alto mare :doh:
{
proc P(ref int y, result int z , name int w)
{
int x = 4 ;
y = ++x + y++;
write (y+x, w);
z = w + 3;
write(y++);
}
int x = 3 ;
int y = 4 ;
P(x, y, x+y);
write(y, x) ;
}
in base a quanto detto, il corpo della procedura P può essere sostituito con:
int x = 4;
x = x + 1; // vale 5;
y = y + x; // vale 3 + 5 = 8
y = y + 1; // vale 9
// poichè y è per riferimento, l'x più esterno viene posto al valore di y
// quindi y vale 9
write (y+x, w);
considerando fino al primo write(), y+x stampa 9+5 = 14, mentre per w (passaggio per nome), viene rivalutato x+y (ma appartenenti al blocco esterno), quindi abbiamo 9 + 4 = 13. BAGLIATO dove sbaglio? :doh:
malocchio
06-08-2009, 15:55
@malocchio: come mai così tanto stupore? :fagiano:
Non posso pensare la mia vita senza operatori di incremento/decremento :cry:
banryu79
06-08-2009, 15:56
Dove sbaglio?
Sì però se uno arriva a scrivere una roba del genere:
...
int result = functionCall(a++, a, 2*a--, eChiPiùNeHaPiùNeMetta...);
...
è giusto che soffra come un cane dei bug più rognosi e bastardi che gli possano capitare nella sua esperienza di programmazione, e che il compilatore gli esploda sotto il sedere :asd:
:read:
Si scherza eh :D
:read:
Si scherza eh :D
eh :p putroppo sono esercizi d'esame, visto che sei un patito dell'incremento/descremento, potresti anche dire la tua sul risultato della stampa di sopra?
:help:
malocchio
06-08-2009, 16:00
credevo di aver capito, ma il seguente piccolo esercizio (scope statico) mi ha rispedito in alto mare :doh:
{
proc P(ref int y, result int z , name int w)
{
int x = 4 ;
y = ++x + y++;
write (y+x, w);
z = w + 3;
write(y++);
}
int x = 3 ;
int y = 4 ;
P(x, y, x+y);
write(y, x) ;
}
in base a quanto detto, il corpo della procedura P può essere sostituito con:
int x = 4;
x = x + 1; // vale 5;
y = y + x; // vale 3 + 5 = 8
y = y + 1; // vale 9
// poichè y è per riferimento, l'x più esterno viene posto al valore di y
// quindi y vale 9
write (y+x, w);
considerando fino al primo write(), y+x stampa 9+5 = 14, mentre per w (passaggio per nome), viene rivalutato x+y (ma appartenenti al blocco esterno), quindi abbiamo 9 + 4 = 13. BAGLIATO dove sbaglio? :doh:
Mia curiosità+ignoranza: che linguaggio è?
Mia curiosità+ignoranza: che linguaggio è?
un generico linguaggio C-like. Se hai voglia/tempo, prova a dirmi cosa stampa, ho la soluzione. Le mie prime due cifre stampate sono errate. :read:
malocchio
06-08-2009, 16:26
un generico linguaggio C-like. Se hai voglia/tempo, prova a dirmi cosa stampa, ho la soluzione. Le mie prime due cifre stampate sono errate. :read:
Che significa passaggio by result/by name?
Che significa passaggio by result/by name?
by result vuol dire che quando la funzione ritorna, il valore del parametro formale z viene copiato nel parametro attuale quindi y. Ma solo quando ritorna, non prima.
by name è una copia dei parametri attuali (x+y) nel parametro formale w, quindi se hai più w devi valutarlo più volte (sostituire con) x+y. w però utilizza l'ambiente del parametro attuale (x+y), non quello definito dentro la funzione.
by name è più complicato a spiegarlo che in pratica, ma non è implementato da nessun linguaggio moderno.
malocchio
06-08-2009, 16:36
by name è più complicato a spiegarlo che in pratica, ma non è implementato da nessun linguaggio moderno.
E ce credo non c'ho capito una mazza :D
marko.fatto
06-08-2009, 18:01
Non posso pensare la mia vita senza operatori di incremento/decremento :cry:
Normalmente per cosa gli usi? Cicli?
basta fare
10.times {|i| puts i}
anzichè fare
for(int i=0;i<10;i++)
cout<<i;
nessuno proprio riesce a capire l'esempio precedente? :help:
astorcas
06-08-2009, 19:51
nessuno proprio riesce a capire l'esempio precedente? :help:
quale? :confused:
quale? :confused:
post #41 pagina 3... e pensare che tutti concordavano sull'incremento/decremento, ma quell'esempio mi ha ucciso :cry:
astorcas
06-08-2009, 20:16
post #41 pagina 3... e pensare che tutti concordavano sull'incremento/decremento, ma quell'esempio mi ha ucciso :cry:
dunque, premettendo che non ho idea di cosa sia il passaggio per nome e che quello che sto per postare può essere pura fantasia ho fatto sto ragionamento qua (non so quanto ci capirai)
fuori P x=3 y=4
dentro P:
x=4
y=5+3=8 (il ++ si perde per strada secondo me perché incrementa un valore non più puntato da y)
z = 7 + 3 quindi assegno per risultato a y -> 10 (quello esterno)
y= y+1 = 5 ---> quindi x -> 5 (esterno)
cioè usciti da quel putiferio y dovrebbe valere 10 e x 5, però ho praticamente ignorato quel passaggio di valore per nome perciò... booooh
dunque, premettendo che non ho idea di cosa sia il passaggio per nome e che quello che sto per postare può essere pura fantasia ho fatto sto ragionamento qua (non so quanto ci capirai)
fuori P x=3 y=4
dentro P:
x=4
y=5+3=8 (il ++ si perde per strada secondo me perché incrementa un valore non più puntato da y)
y=8
y=y+1=9
z = 7 + 3 quindi assegno per risultato a y -> 10 (quello esterno)
y= y+1 = 5 ---> quindi x -> 5 (esterno)
cioè usciti da quel putiferio y dovrebbe valere 10 e x 5, però ho praticamente ignorato quel passaggio di valore per nome perciò... booooh
quale incremento si perde per strada? :confused: y++? in quel caso, perchè hai scritto dopo y=y+1=9? dovrebbe restare 8, se dici che l'incremento si perde (anche se non ho capito perchè, con 8 il risultato dovrebbe essere esatto :mbe: )
astorcas
06-08-2009, 20:38
quale incremento si perde per strada? :confused: y++? in quel caso, perchè hai scritto dopo y=y+1=9? dovrebbe restare 8, se dici che l'incremento si perde (anche se non ho capito perchè, con 8 il risultato dovrebbe essere esatto :mbe: )
si scusa dovrebbe rimanere ad 8. Il libro che dice?
si scusa dovrebbe rimanere ad 8. Il libro che dice?
il libro da solo la sequenza finale, che è:
In questo caso il risultato `e indipendente dall’ordine di valutazione delle espressioni e dall’ordine
di calcolo di l-value e r-value nell’assegnamento.
L’output `e 13, 12, 8, 15, 9.
non preoccuparti per il passaggio per nome, quello sono abbastanza sicuro. Resta da capire perchè si perde per strada l'incremento, quando tutti dicono il contrario.
es. qui, similmente risposta numero 7 (http://www.allinterview.com/showanswers/5271.html)
astorcas
06-08-2009, 20:48
il libro da solo la sequenza finale, che è:
In questo caso il risultato `e indipendente dall’ordine di valutazione delle espressioni e dall’ordine
di calcolo di l-value e r-value nell’assegnamento.
L’output `e 13, 12, 8, 15, 9.
non preoccuparti per il passaggio per nome, quello sono abbastanza sicuro. Resta da capire perchè si perde per strada l'incremento, quando tutti dicono il contrario.
es. qui, similmente risposta numero 7 (http://www.allinterview.com/showanswers/5271.html)
sono confuso, quindi se quel che dico, cioè che l'incremento si perde, è vero ti torna l'esercizio? Se si è vero che poi mi fai capire pure a me? :D
EDIT: ecco per esempio io al tuo link risponderei x=56, y=93
ecco spiegato spero sia chiaro. Se non consideriamo l'incremento di y, si trova tutto. Qualcuno ha idea del perchè y non venga incrementato?
proc P(ref int y, result int z , name int w)
{
int x = 4 ;
y = ++x + y++; // y = 8, x = 5, x est = 8 per il passaggio per
// riferimento
write (y+x, w); // y+x **STAMPA 13, poi a w sostituiamo x+y riferiti però
// all'ambiente del blocco esterno, quindi x est. = 8, y est. = 4,
// **STAMPA 12
z = w + 3; // z = 12 + 3 (w = x+y sempre rispetto all'ambiente esterno)
write(y++); // **STAMPA 8, poi incrementa (y = 9)
// siamo al return, quindi x est. = 9, in y est. si copia il valore
// di z (passaggio per risultato) quindi y est. = 15
}
int x = 3 ;
int y = 4 ;
P(x, y, x+y);
write(y, x) ; // **STAMPA 15, 9
}
astorcas
06-08-2009, 21:09
Ecco credo questo possa aiutarti a capire http://faq.javaranch.com/java/PostIncrementOperatorAndAssignment
Ecco credo questo possa aiutarti a capire http://faq.javaranch.com/java/PostIncrementOperatorAndAssignment
ottimo esempio :read:, quindi post incremento/decremento è completamente ignorato nell'assegnameno :eek: Ma se scrivo foo(a[i++])? dopo l'incrementa o no? oppure una chiamata a funzione G(v-- + v) che fa?
resta da capire se l'ordine di calcolo di l-valore e r-valore possa influenzare questo comportamento.
@ Gremo: ma scusa x è stato ridefinito dentro la funzione, perchè l'incremento dovrebbe incrementarti anche l'x esterno?
EDIT:
ottimo esempio :read:, quindi post incremento/decremento è completamente ignorato nell'assegnameno :eek: Ma se scrivo foo(a[i++])? dopo l'incrementa o no? oppure una chiamata a funzione G(v-- + v) che fa?
valgono le considerazioni fatte prima, quindi v--+v vale 6 (per v=3)
resta da capire se l'ordine di calcolo di l-valore e r-valore possa influenzare questo comportamento.
Ma a te basta che l'istruzione esegua il comportamento che viene specificato: questi sono dettagli dell'implementazione che a te non devono interessarti, salvo casi particolari... comunque credo sia ininfluente: ogni occorrenza della variabile v viene restituita dalla "oldvariable" e alla fine viene reincrementata v...
@ Gremo: ma scusa x è stato ridefinito dentro la funzione, perchè l'incremento dovrebbe incrementarti anche l'x esterno?
l'x esterno infatti non viene toccato dall'incremento (il primo diretto pre-incremento). Leuniche modifiche che subisce sono a causa della variabile y, perchè passata per riferimento...
dove ho scritto che modifico la x esterna incrementandola?
astorcas
06-08-2009, 21:49
ottimo esempio :read:, quindi post incremento/decremento è completamente ignorato nell'assegnameno :eek: Ma se scrivo foo(a[i++])? dopo l'incrementa o no? oppure una chiamata a funzione G(v-- + v) che fa?
resta da capire se l'ordine di calcolo di l-valore e r-valore possa influenzare questo comportamento.
in foo(a[i++]) la funzione viene chiamata col valore i prima dell'incremento, ma viene incrementata immediatamente (se per esempio i è globale già all'interno di foo i vale 1 in più del parametro che viene passato alla funzione), Per il secondo caso la prima v è non decrementata e la seconda si.
Mi hai chiarito un bel po' le idee (o meglio non mi ero mai fatto pippe del genere in merito, grazie!)
in foo(a[i++]) la funzione viene chiamata col valore i prima dell'incremento, ma viene incrementata immediatamente (se per esempio i è globale già all'interno di foo i vale 1 in più del parametro che viene passato alla funzione), Per il secondo caso la prima v è non decrementata e la seconda si.
Mi hai chiarito un bel po' le idee (o meglio non mi ero mai fatto pippe del genere in merito, grazie!)
a poco a poco le chiarisco anche io :stordita: ma ho molti altri esercizi da verificare, speriamo bene. Se c'è qualcosa che non mi torna proveddo a postare :p
dove ho scritto che modifico la x esterna incrementandola?
qui:
proc P(ref int y, result int z , name int w)
{
int x = 4 ;
y = ++x + y++; // y = 8, x = 5, x est = 8 per il passaggio per
// riferimento
write (y+x, w); // y+x **STAMPA 13, poi a w sostituiamo x+y riferiti però
// all'ambiente del blocco esterno, quindi x est. = 8, y est. = 4,
// **STAMPA 12
z = w + 3; // z = 12 + 3 (w = x+y sempre rispetto all'ambiente esterno)
write(y++); // **STAMPA 8, poi incrementa (y = 9)
// siamo al return, quindi x est. = 9, in y est. si copia il valore
// di z (passaggio per risultato) quindi y est. = 15
}
int x = 3 ;
int y = 4 ;
P(x, y, x+y);
write(y, x) ; // **STAMPA 15, 9
}
o sono io che ho interpretato male?
astorcas
06-08-2009, 22:00
qui:
proc P(ref int y, result int z , name int w)
{
int x = 4 ;
y = ++x + y++; // y = 8, x = 5, x est = 8 per il passaggio per
// riferimento
write (y+x, w); // y+x **STAMPA 13, poi a w sostituiamo x+y riferiti però
// all'ambiente del blocco esterno, quindi x est. = 8, y est. = 4,
// **STAMPA 12
z = w + 3; // z = 12 + 3 (w = x+y sempre rispetto all'ambiente esterno)
write(y++); // **STAMPA 8, poi incrementa (y = 9)
// siamo al return, quindi x est. = 9, in y est. si copia il valore
// di z (passaggio per risultato) quindi y est. = 15
}
int x = 3 ;
int y = 4 ;
P(x, y, x+y);
write(y, x) ; // **STAMPA 15, 9
}
o sono io che ho interpretato male?
la y all'interno della funzione non è altro che la x esterna passata per riferimento, quindi sono la stessa cosa, se y=8 è esattamente come dire x=8 :)
qui:
proc P(ref int y, result int z , name int w)
{
int x = 4 ;
y = ++x + y++; // y = 8, x = 5, x est = 8 per il passaggio per
// riferimento
write (y+x, w); // y+x **STAMPA 13, poi a w sostituiamo x+y riferiti però
// all'ambiente del blocco esterno, quindi x est. = 8, y est. = 4,
// **STAMPA 12
z = w + 3; // z = 12 + 3 (w = x+y sempre rispetto all'ambiente esterno)
write(y++); // **STAMPA 8, poi incrementa (y = 9)
// siamo al return, quindi x est. = 9, in y est. si copia il valore
// di z (passaggio per risultato) quindi y est. = 15
}
int x = 3 ;
int y = 4 ;
P(x, y, x+y);
write(y, x) ; // **STAMPA 15, 9
}
o sono io che ho interpretato male?
no credo sia chiaro, la x esterna (PUR essendo oscurata) è comunque subito modificata dopo la riga che hai evidenziato in grassetto, perchè il passaggio di parametri è per riferimento, quindi le modifiche a y si riflettono immediatamente su x est.
ps. grazie per l'altro post, anche se su G(v-- + v) astorcas la pensa diversamente. Man mano che vado avanti negli esempio chiarirò anche questo (se non altro per esclusione...avendo i risultati :p )
la y all'interno della funzione non è altro che la x esterna
Vero che idiota :doh:
cdimauro
07-08-2009, 16:42
Mmmh da una googlata veloce vedo che hai ragione... scelta curiosa.
Questione di chiarezza del codice. E' già tanto che abbiano introdotto gli operatori di assegnazione, che alcuni pythonisti non vedono nemmeno di buon occhio e vorrebbero fossero soppressi. :p
Non posso pensare la mia vita senza operatori di incremento/decremento :cry:
Sì che si può, e questo thread ne è la dimostrazione: senza di essi il codice sarebbe più chiaro e meno affetto da "effetti collaterali" dovuti all'ordine di valutazione scelto dal compilatore.
Tra parentesi, in C e C++ l'unico ordine che viene garantito è quello della valutazione degli operatori logici, rigorosamente da sinistra a destra.
Per il resto il compilatore può fare tutte le porcate che vuole. E se poi usate le macro... no comment. :D
banryu79
07-08-2009, 16:48
Da cui si arriva alla "conclusione" che avevo già postato due pagine fa:
Sì però se uno arriva a scrivere una roba del genere:
...
int result = functionCall(a++, a, 2*a--, eChiPiùNeHaPiùNeMetta...);
...
è giusto che soffra come un cane dei bug più rognosi e bastardi che gli possano capitare nella sua esperienza di programmazione, e che il compilatore gli esploda sotto il sedere
Rassegnatevi o lasciate esplodere i vostri compilatori http://www.bilderkiste.de/phpcliparts/media/smilie_bombe.gif
astorcas
07-08-2009, 16:59
Questione di chiarezza del codice. E' già tanto che abbiano introdotto gli operatori di assegnazione, che alcuni pythonisti non vedono nemmeno di buon occhio e vorrebbero fossero soppressi. :p
Sì che si può, e questo thread ne è la dimostrazione: senza di essi il codice sarebbe più chiaro e meno affetto da "effetti collaterali" dovuti all'ordine di valutazione scelto dal compilatore.
Tra parentesi, in C e C++ l'unico ordine che viene garantito è quello della valutazione degli operatori logici, rigorosamente da sinistra a destra.
Per il resto il compilatore può fare tutte le porcate che vuole. E se poi usate le macro... no comment. :D
inizio a pensare che van Rossum la sappia davvero lunga, quoto!
malocchio
07-08-2009, 17:40
Sì che si può, e questo thread ne è la dimostrazione: senza di essi il codice sarebbe più chiaro e meno affetto da "effetti collaterali" dovuti all'ordine di valutazione scelto dal compilatore.
Tra parentesi, in C e C++ l'unico ordine che viene garantito è quello della valutazione degli operatori logici, rigorosamente da sinistra a destra.
Per il resto il compilatore può fare tutte le porcate che vuole. E se poi usate le macro... no comment. :D
Non si può neanche scherzare :cry: :cry:
ot: Ho trovato questo server svn gratuito (http://www.visualsvn.com/server) con snap-in per Windows, sembra buono...:D
cdimauro
07-08-2009, 20:14
inizio a pensare che van Rossum la sappia davvero lunga, quoto!
Questo non lo so, ma posso dirti, seguendo la mailing list degli sviluppatori, che è un accanito sostenitore della chiarezza e didatticità del codice, e per questo difficilmente è disposto a scendere a compromessi.
Ha introdotto le lambda function = funzioni anonime a malincuore, e aveva in mente di toglierle di mezzo già con Python 3, ma è stato fermato dalla moltitudine di sviluppatori che li trova comodi (forse ritenterà con la versione 4).
Figurati, per dirne un'altra, che non ha alcuna intenzione di introdurre la tail recursion in CPython, soltanto perché lo stack trace delle chiamate non sarebbe fedele all'ordine delle chiamate (con la tail recursion in genere si "ricicla" lo stack). Questo perché lui vuole fermamente che chi si avvicina al linguaggio debba avere sempre tutto chiaro di ciò che succede.
Considera che la chiamata a funzione è abbastanza lenta in CPython, e con ottimizzazioni come questa ne trarrebbe non poco vantaggio, ma è irremovibile.
Non si può neanche scherzare :cry: :cry:
:Perfido:
è giusto che soffra come un cane dei bug più rognosi e bastardi che gli possano capitare nella sua esperienza di programmazione, e che il compilatore gli esploda sotto il sedere :asd:
Chiunque scriva un'espressione in cui il risultato dipende dall'ordine di valutazione degli argomenti si merita tutto il male a cui va incontro :D, anche quando tale ordine e' definito chiaramente dal linguaggio (a parte le rare eccezioni).
E la cosa riguarda non solo i semplici operatori di incremento/decremento, ma qualsiasi funzione che abbia effetti collaterali (uno puo' farsi del male in maniera analoga in python o ruby tanto per intendersi).
visto che sei un patito dell'incremento/descremento,
:help:
:mbe:
by name è più complicato a spiegarlo che in pratica, ma non è implementato da nessun linguaggio moderno.
Direi che le macro igieniche di scheme si possono considerare call by name.
chiarimento: La call by name e' fondamentalmente equivalente alla macro espansione con la differenza che protegge dalla cattura accidentale dei nomi di variabile.
zulutown
09-08-2009, 09:24
comunque la cosa allucinante è che in un corso universitario vengano fatti esami per districarsi in codice scritto col culo con operatori di incremento decremento infilati all'interno di espressioni complesse che qualunque sviluppatore dotato di un minimo di cervello non userebbe mai altrimenti.
Ed_Bunker
09-08-2009, 09:28
E' la stessa affermazione che molti sviluppatori "senza cervello" hanno fatto qualche anno prima di realizzare quel codice...
:D
Ikon O'Cluster
15-08-2009, 01:59
Ultimo caso. Se ho una chiamata a funzione:
v = 3;
G(v-- + R(v))
dove R è un'altra funzione, come viene valutato ciò che è dentro G? Viene chiamato G(3 + R(2)), o G(3 + R(3)) e al ritorno della chiamata viene decrementato v?
Direi che questo esercizio non aveva tanto lo scopo di far capire l'ordine di valutazione degli operandi, quanto quello di fa capire l'importanza nell'uso delle parentesi. Spesso anche quando non servono aiutano chi legge il codice. Ovviamente meglio non esagerare. Ad esempio:
var = ((a == b) ? c : d);
Non fa così male piazzare 4 parentesi. Quindi anche quando si pensa di essere sicuri, ci si mettono due belle parentesi in modo tale che tutto diventi evidente anche per chi legge, ma soprattutto non si perderà tempo a trovare bug invisibili!
Nella fattispecie consiglierei un:
G((v--) + R(v))
In modo da far capire che l'intenzione era quella di calcolare G(2+R(2))...
Ikon O'Cluster
18-08-2009, 01:51
un generico linguaggio C-like
Ma perchè al prof risulta molto difficile scriver in C o Java??? Potrebbe anche impararlo un linguaggio :) ahuahuauha
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.