Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[SFOGO] Distruttore... e VS2008

0 views
Skip to first unread message

GuGu

unread,
Jul 14, 2008, 9:54:33 AM7/14/08
to
Ho un Merlo che e' da stamattina sta spostando mattoni per una
pavimentazione con quel cicalino trapanatimpani per la retromarcia.
Pure con le finestre chiuse si sente quel BIIIP... BIIIIP... BIIIIP...
BIIIIP...
Chi mi implementa un distruttore per quel noioso cicalino?
Purtroppo non ho la classe CMerlo, ma solo la classe CLeo derivata da
CAutista che ha un puntatore all'istanta di CMerlo che sta guidando e ho una
classe CGugu (me stesso) che e' friend di CLeo. Ho provato a chiamare il
metodo SpegniCicalino ma non lo compila perche' CLeo non implementa questo
metodo. Ho provato anche a farmi passare il puntatore all'istanza di CMerlo
ma non ho trovato nessun metodo esplicito ma soltanto un paio di
FuseInsert/FuseRemove che dovrebbero andare bene. Non avete un amico
elettrauto che vi dice quale ID passare alla FuseRemove per disattivare sto
@#$%& di cicalino????????????

Domanda seria invece, ho appena installato il VS2008 e comincero' a migrare
un progetto scritto in VS6.0 abbastanza grossino.
Ovviamente ci sono parecchie cose non standard C++ che dovro' andare a
sistemare per far sparire un po' di errori durante la compilazione.
Avete esperienza se posso limitarmi a sistemare i vari errori e/o warning
che verranno fuori oppure se dalla versione del C++ implementata al VS6.0 a
quella del VS2008 c'e' effettivamente qualche vecchia pratica che e'
assolutamente da dimenticare onde evitare errori subdoli molto gravi?

Faccio un esempio concreto: ho scoperto che facendo compilare al VS2005 un
pezzo di codice che fa uso del post-incremento:

A = B[i++] + B[i++] + B[i++];

invece di funzionare come nel VS6.0 in qualcosa tipo:

A = B[i] + B[i+1] + B[i+2];
i+=3;

E' diventato

A = B[i] + B[i] + B[i];
i+=3;

Non ho investigato troppo su questo problema, avevo urganza di farlo
funzionare quindi ho tolto il post-incremento.
E' qualche balla del 2005, qualche parametro non settato correttamente
oppure mi posso aspettare che nel 2008 mi trovo cose che non funzionano piu'
come funzionavano una volta?


Max M.

unread,
Jul 14, 2008, 10:08:58 AM7/14/08
to
GuGu wrote:
> Faccio un esempio concreto: ho scoperto che facendo compilare al VS2005 un
> pezzo di codice che fa uso del post-incremento:
>
> A = B[i++] + B[i++] + B[i++];

L'espressione viola questa regola:

"Between the previous and next sequence point an object shall have its
stored value modified at most once by the evaluation of an expression.
Furthermore, the prior value shall be accessed only to determine the value
to be stored."


> E' qualche balla del 2005, qualche parametro non settato correttamente
> oppure mi posso aspettare che nel 2008 mi trovo cose che non funzionano
> piu' come funzionavano una volta?

Se non si rispettano le regole del linguaggio, le cose possono "funzionare"
diversamente a seconda del compilatore, della versione o della situazione
atmosferica locale.

Max

GuGu

unread,
Jul 14, 2008, 10:34:15 AM7/14/08
to
> Se non si rispettano le regole del linguaggio, le cose possono
> "funzionare"
> diversamente a seconda del compilatore, della versione o della situazione
> atmosferica locale.


E quindi non mi devo limitare a correggere gli errori/warning del
compilatore, ma mi tocca andare a verificare riga per riga che non siano
state commessi errori del genere. Questi sorgenti che devo convertire sono
stati scritti nel corso di 10 anni da 8 persone circa (450 files sorgenti e
10 mega di codice). Mi sa che mi aspettano lunghi mesi di test...

P.S. Per Andrea laforgia: lo so che hai ragione quando mi scrivevi che in
programmazione bisogna imparare a costruire casi di test e non affidarsi ai
messaggi del compilatore, ma se conosci qualche compilatore (anche non
VS2008 a questo punto) che mi possa generare un bel po' di WARNING per dare
una bella sgrossata a problemi simili che mi possono capitare... sarebbe
cosa graditissima.

Andrea Laforgia

unread,
Jul 14, 2008, 11:23:39 AM7/14/08
to
On 14 Lug, 16:34, "GuGu" <promp...@tiscali.it> wrote:

> P.S. Per Andrea laforgia: lo so che hai ragione quando mi scrivevi che in
> programmazione bisogna imparare a costruire casi di test e non affidarsi ai
> messaggi del compilatore

Espressioni che non rispettano la regola dei sequence point potrebbero
sfuggire anche al test.
Se con un compilatore hai sempre un dato comportamento, allora ti
sembra che le cose vadano bene e non sei motivato a cambiarle. Tu ti
sei accorto dell'errore perché hai cambiato compilatore. Anche facendo
i test col VS6.0, ti sarebbe sembrato tutto ok. Il fatto è che chi
programma dovrebbe avere delle conoscenze di base forti sul linguaggio
tanto da sapere che non è bene abusare delle istruzioni con side
effect.

>, ma se conosci qualche compilatore (anche non
> VS2008 a questo punto) che mi possa generare un bel po' di WARNING per dare
> una bella sgrossata a problemi simili che mi possono capitare... sarebbe
> cosa graditissima.

Il gcc ha le opzioni -Wall e -pedantic (ed altri flag per l'aderenza
stretta allo standard ISO) ma se il tuo codice è stato costruito per
Visual C++, devi compilarlo con quest'ultimo. Ti dico "devi" non nel
senso di obbligo, ma perché è molto poco presumibile che il tuo codice
compili anche col gcc. Di solito quando si tira su un'applicazione si
usano - benché sarebbe bene che fossero in minima parte -
caratteristiche legate al particolare compilatore. Se hai il "core"
del tuo sistema ben isolato in classi conformi allo standard puoi
provare a compilarle col gcc, come ti ho detto.

GuGu

unread,
Jul 14, 2008, 12:03:08 PM7/14/08
to
> Il fatto è che chi programma dovrebbe avere delle conoscenze di base forti
> sul linguaggio tanto da sapere che non è bene abusare delle istruzioni con
> side effect.

Purtroppo come avrai gia' intuito c'e' un po' di tutto qua dentro. Stamani
ho scaricato e stampato il "tomo" di Eckel, io e il mio collega vedremo di
rispolverare il nostro background partendo da li, perche' ho la sensazione
che ci aspetta un lavoro non proprio semplice.

> Se hai il "core" del tuo sistema ben isolato in classi conformi allo
> standard puoi provare a compilarle col gcc, come ti ho detto.

Tolto una manciata di sorgenti contenenti routine matematiche di vario
genere (alcune delle quali scritte in C), il resto e' stato abbastanza
mischiato anche se sono state ben separati i metodi che si occupano per
esempio dell'interfaccia utente da quelli che fanno elaborazione pura. Stavo
valutando che mi converrebbe sdoppiare tutte le classi che contengono metodi
specifici per l'interfaccia utente cercando di ottenere classi su due
livelli distinti.
In questa prima fase farei dei copia & incolla, intervenendo il meno
possibile sul codice e potrei operare sempre con VS6.0.
Nella seconda fase estirpare tutto quello che c'e' di MFC nelle classi base
(CString, CArray tanto per citarne un paio) e reimplementarle (std:string,
std:vector, etc.)
Quindi divertirmi con il GCC sulle classi basi per andare a caccia per
quanto possibile di errori/orrori di vario genere e infine portare tutto su
VS2008.
Se ci sono soluzioni piu' rapide e indolori sono ben accette.

Andrea Laforgia

unread,
Jul 14, 2008, 1:58:49 PM7/14/08
to
On Mon, 14 Jul 2008 18:03:08 +0200, "GuGu" <prom...@tiscali.it>
wrote:

>ho scaricato e stampato il "tomo" di Eckel, io e il mio collega vedremo di
>rispolverare il nostro background partendo da li

Lodevole iniziativa.

>Tolto una manciata di sorgenti contenenti routine matematiche di vario
>genere (alcune delle quali scritte in C), il resto e' stato abbastanza
>mischiato anche se sono state ben separati i metodi che si occupano per
>esempio dell'interfaccia utente da quelli che fanno elaborazione pura.

E te pareva.

>Stavo
>valutando che mi converrebbe sdoppiare tutte le classi che contengono metodi
>specifici per l'interfaccia utente cercando di ottenere classi su due
>livelli distinti.

Non conoscendo nello specifico il tuo progetto non so che cosa ti
converrebbe fare, però, come "rule of thumb" generale (in realtà è
molto più che una "rule of thumb") ti conviene separare le
responsabilità secondo il sempreverde modello del
Model-View-Controller. Le classi con logica applicativa devono stare
da una parte, quelle di gestione di interfaccia dall'altra.

>Nella seconda fase estirpare tutto quello che c'e' di MFC nelle classi base
>(CString, CArray tanto per citarne un paio) e reimplementarle (std:string,
>std:vector, etc.)

Non sarebbe affatto male. Abbastanza invasiva come modifica. Pensaci
bene prima di toccare un'applicazione così "ingessata".

>Quindi divertirmi con il GCC sulle classi basi per andare a caccia per
>quanto possibile di errori/orrori di vario genere e infine portare tutto su
>VS2008.

Se hai un po' d'esperienza col C e col C++, gli errori/orrori li
individui abbastanza facilmente. Sicuramente esistono implementazioni
moderne di tool come il vecchio lint. Quello che posso dirti è che il
gcc, con le opzioni che ti ho suggerito, ti fa veramente le pulci.
Ora, non conosco sufficientemente bene VC++ 2008, però credo che
l'aderenza allo standard sia di molto migliorata ed è possibilissimo
che abbia diagnostiche avanzate tanto quanto quelle del gcc.

softwareEngineer

unread,
Jul 14, 2008, 5:24:57 PM7/14/08
to
C'è una cosa del genere anche con VStudio "/Wall" oppure "/W4"
- /Wall - Enables all warnings, including those disabled by default
- /W4 - Level 4 displays all level 3 warnings plus informational warnings,
which in most cases can be safely ignored. This option should be used only
to provide "lint" level warnings and is not recommended as your usual
warning level setting. For a new project, it may be best to use /W4 in all
compilations. This will ensure the fewest possible hard-to-find code
defects.

Tasto destro sul progetto, Properties, C/C++, General, Warning Level.

By.

GuGu

unread,
Jul 15, 2008, 2:39:38 AM7/15/08
to
> Non conoscendo nello specifico il tuo progetto non so che cosa ti
> converrebbe fare, però, come "rule of thumb" generale (in realtà è
> molto più che una "rule of thumb") ti conviene separare le
> responsabilità secondo il sempreverde modello del
> Model-View-Controller. Le classi con logica applicativa devono stare
> da una parte, quelle di gestione di interfaccia dall'altra.

Copy that, e' proprio la direzione che pensavo di seguire.

> Se hai un po' d'esperienza col C e col C++, gli errori/orrori li
> individui abbastanza facilmente. Sicuramente esistono implementazioni
> moderne di tool come il vecchio lint. Quello che posso dirti è che il
> gcc, con le opzioni che ti ho suggerito, ti fa veramente le pulci.
> Ora, non conosco sufficientemente bene VC++ 2008, però credo che
> l'aderenza allo standard sia di molto migliorata ed è possibilissimo
> che abbia diagnostiche avanzate tanto quanto quelle del gcc.

VC e' quello che passa il convento purtroppo!
Pero'... mi pare di capire che oltre alla gestione del FW3.5 il 2008 in
pratica e' un 2005 ripulito di bugs e aggiornato sullo standard.
Spero solo che tra due anni non esca un VC++2010 e che ci sia tutto da
rifare!!!

Andrea Laforgia

unread,
Jul 15, 2008, 4:23:18 AM7/15/08
to

> Spero solo che tra due anni non esca un VC++2010 e che ci sia tutto da
> rifare!!!

Se ti atterrai allo standard ISO, questo pericolo è scongiurato.

Federico Zenith

unread,
Jul 15, 2008, 4:19:38 AM7/15/08
to
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

GuGu wrote:
> E quindi non mi devo limitare a correggere gli errori/warning del
> compilatore, ma mi tocca andare a verificare riga per riga che non siano
> state commessi errori del genere. Questi sorgenti che devo convertire
> sono stati scritti nel corso di 10 anni da 8 persone circa (450 files
> sorgenti e 10 mega di codice). Mi sa che mi aspettano lunghi mesi di
> test...
>
> P.S. Per Andrea laforgia: lo so che hai ragione quando mi scrivevi che
> in programmazione bisogna imparare a costruire casi di test e non
> affidarsi ai messaggi del compilatore, ma se conosci qualche compilatore
> (anche non VS2008 a questo punto) che mi possa generare un bel po' di
> WARNING per dare una bella sgrossata a problemi simili che mi possono
> capitare... sarebbe cosa graditissima.

Mi sono incuriosito perché questa cosa non la sapevo... g++ (GCC) è in
grado di segnalare un warning al riguardo: vedi il seguente programma:

- ----------------
#include <iostream>

int main()
{
int pippo[3];
int i = 0;

pippo[0] = 1;
pippo[1] = 2;
pippo[2] = 4;

int Total = pippo[i++] + pippo[i++] + pippo[i++];

std::cout << Total << std::endl;

return 0;
}
- ---------------

compilandolo con 'g++ test.cpp -o test -Wall' ottieni un avviso del tipo:

- ----------------
test.cpp: In function ‘int main()’:
test.cpp:12: warning: operation on ‘i’ may be undefined
test.cpp:12: warning: operation on ‘i’ may be undefined
- ----------------

Per la cronaca, il programma stampa un valore «sbagliato» (3 invece di
7). La mia versione di g++ (GCC) è 4.1.2 20061115.

Ciao,
- -Federico
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (GNU/Linux)
Comment: Using GnuPG with SUSE - http://enigmail.mozdev.org

iD8DBQFIfF2aBIpu+y7DlLcRArv0AKCfpuPJN4W0fZOVACX4nQUu8rdK8wCcD63V
rN78PBGsy1CJgILRPv8e1NI=
=vqV3
-----END PGP SIGNATURE-----

GuGu

unread,
Jul 15, 2008, 4:38:53 AM7/15/08
to
> C'è una cosa del genere anche con VStudio "/Wall" oppure "/W4"


Non ho resistito e' ho provato subito: 2075 errore/i, 1219 avviso/i
I warning sono prevalentemente deprecation e unsafe.
Gli errori sono mancanze di void e lo scope delle variabili definite nei for
e istanziate successivamente che segnala indefinite.
Ci sono pezzi scritti in C++ ma con uno stile che ricorda tantissimo il C.
Speriamo in bene!

GuGu

unread,
Jul 15, 2008, 4:44:23 AM7/15/08
to
> Mi sono incuriosito perché questa cosa non la sapevo... g++ (GCC) è in
> grado di segnalare un warning al riguardo:

Ho provato con il VC++2008 e non segnala nessun warning (ho usato W4) ma il
risultato e' 3.
Esattamente come mi succedeva con il VC+2005...
Mi sa che dove posso utilizzero' il GCC, se non altro per provare a
compilare il codice e vedere cosa mi segnala lui.

softwareEngineer

unread,
Jul 15, 2008, 4:55:33 AM7/15/08
to

Nel mio precedente progetto (c++ ovviamente) compilavamo con warning
level 4 e devo
dire che a regime è un'ottima cosa .... ti ritrovi con molti meno
errori e warning !!
in bocca al lupo :-)

by.

GuGu

unread,
Jul 15, 2008, 5:06:05 AM7/15/08
to
> Nel mio precedente progetto (c++ ovviamente) compilavamo con warning
> level 4 e devo dire che a regime è un'ottima cosa .... ti ritrovi con
> molti meno
> errori e warning !!

Si, mi piace molto questa cosa.

> in bocca al lupo :-)

grasssie!

Max M.

unread,
Jul 15, 2008, 5:18:32 AM7/15/08
to
Federico Zenith wrote:
>
> Per la cronaca, il programma stampa un valore «sbagliato» (3 invece di
> 7). La mia versione di g++ (GCC) è 4.1.2 20061115.
>

Beh, 3 è tanto "sbagliato" quanto 7.

Ad ogni modo, bisogna tenere comqunque presente che il compilatore non può
sempre diagnosticare questo tipo di violazioni. Ad esempio, questo codice

int& func( int& i ) { return ++i; }

A = B[ func(i) ] + B[ func(i) ];

non produce alcun warning, ma è tanto sbagliato quanto l'altro.

Max

GuGu

unread,
Jul 15, 2008, 6:03:20 AM7/15/08
to
> Ad ogni modo, bisogna tenere comqunque presente che il compilatore non può
> sempre diagnosticare questo tipo di violazioni. Ad esempio, questo codice
>
> int& func( int& i ) { return ++i; }
>
> A = B[ func(i) ] + B[ func(i) ];
>
> non produce alcun warning, ma è tanto sbagliato quanto l'altro.


Secondo me l'esempio che hai scritto invece e' corretto.
Sarebbe sbagliato scritto in questo modo
A = B[ func(i) ] / B[ func(i) ];

Andrea Laforgia

unread,
Jul 15, 2008, 6:17:47 AM7/15/08
to
On 15 Lug, 12:03, "GuGu" <promp...@tiscali.it> wrote:

> Secondo me l'esempio che hai scritto invece e' corretto.
> Sarebbe sbagliato scritto in questo modo
>     A = B[ func(i) ]  / B[ func(i) ];

Vedo che parlare del pericolo side-effect non è servito a niente :-)
Ha ragione Max: l'errore è nel fare affidamento sul fatto che le
operazioni vengano svolte in una sequenza precisa, quando non è così.
Non dipende dall'operazione aritmetica specifica. Se scrivi:

A = B[func(i)] + B[func(i)];

non sai quando e in che ordine, nello specifico, le due chiamate a
funzione func(i) vengono eseguite, perché non sai in che punto del
calcolo dell'espressione, il compilatore piazza il sequence point,
cioè il momento di "quiete" in cui si dedica ai "side-effect".

GuGu

unread,
Jul 15, 2008, 8:18:16 AM7/15/08
to
> Ha ragione Max: l'errore è nel fare affidamento sul fatto che le
> operazioni vengano svolte in una sequenza precisa, quando non è così.

Si ma forse non ho capito: nell'esempio specifico riportato da Max dove ha
usato un operatore è che gode della proprieta' commutativa l'ordine con cui
verranno eseguite le due funzioni e' assolutamente ininfluente.

> non sai quando e in che ordine, nello specifico, le due chiamate a
> funzione func(i) vengono eseguite, perché non sai in che punto del
> calcolo dell'espressione, il compilatore piazza il sequence point,
> cioè il momento di "quiete" in cui si dedica ai "side-effect".

Infatti, ma e' proprio quello che pensavo io per questo ho fatto parlato di
+ e /.
Non stiamo dicendo la stessa cosa?

Andrea Laforgia

unread,
Jul 15, 2008, 8:42:54 AM7/15/08
to
On 15 Lug, 14:18, "GuGu" <promp...@tiscali.it> wrote:
> > Ha ragione Max: l'errore è nel fare affidamento sul fatto che le
> > operazioni vengano svolte in una sequenza precisa, quando non è così.
>
> Si ma forse non ho capito: nell'esempio specifico riportato da Max dove ha
> usato un operatore è che gode della proprieta' commutativa l'ordine con cui
> verranno eseguite le due funzioni e' assolutamente ininfluente.

Quello che Max voleva sottolineare nel suo esempio è che, mentre per
l'apparato diagnostico di un compilatore può essere relativamente
semplice individuare casi di uso di variabile con side-effect
pericolosi e quindi sollevare warning, può essere più difficile - se
non impossibile - fare lo stesso quando quei side-effect sono
contenuti in funzioni, perché dovrebbe andare ad investigare, nel
dettaglio, cosa viene fatto in quel codice chiamato.

Il problema, comunque, non è nell'operatore aritmetico usato, nella
sua proprietà commutativa o meno, ma nel fatto che il risultato di
quella funzione func() viene usato per accedere agli elementi di un
array, quindi un indice o un altro determinano un diverso elemento. Se
non c'è un ordine preciso (perché non c'è) nella valutazione di quelle
funzioni, non c'è neanche un criterio preciso di determinazione di
quei valori.

> Non stiamo dicendo la stessa cosa?

Temo di no.

GuGu

unread,
Jul 15, 2008, 9:39:06 AM7/15/08
to
> Quello che Max voleva sottolineare nel suo esempio č che ...

Ho capito quello che Max voleva sottolineare e non posso che essere
daccordo!
Fatto sta che ha scritto un codice che a tutti gli effetti funziona
egregiamente bene su qualsiasi compilatore, nonostante sia concettualmente
errato (per il discorso dei side-effect) e fornisce un risultato corretto!
Era questo che volevo semplicemente dire: se invece del + mette un diviso
allora il suo codice fornisce un risultato imprevedibile a seconda del
compilatore adottato e quindi come esempio mi sembra nettamente piu'
efficace.

Andrea Laforgia

unread,
Jul 15, 2008, 10:05:35 AM7/15/08
to
On 15 Lug, 15:39, "GuGu" <promp...@tiscali.it> wrote:

> Fatto sta che  ha scritto un codice che a tutti gli effetti funziona
> egregiamente bene su qualsiasi compilatore, nonostante sia concettualmente
> errato (per il discorso dei side-effect) e fornisce un risultato corretto!

Scusa, ma non capisco come si accordano tra loro le espressioni
"funziona egregiamente bene" e "nonostante sia concettualmente
errato". E non capisco come puoi essere d'accordo con Max se sta
affermando l'esatto contrario di quello che affermi tu. Se il codice è
concettualmente errato, non fornisce un risultato corretto. E il
codice postato da Max, come egli stesso vuol dimostrare, non produce
necessariamente un risultato corretto perché si basa su effetti
collaterali nella stessa espressione. Quel codice non funziona
"egregiamente bene" a prescindere da qualsiasi compilatore e non
arrivo a cogliere, secondo il tuo punto di vista, quale sia l'aspetto
discriminante tra un'addizione e una divisione nel caso specifico. Non
è dell'operazione aritmetica che si sta discutendo, ma dei side-effect
nell'espressione.

> Era questo che volevo semplicemente dire: se invece del + mette un diviso
> allora il suo codice fornisce un risultato imprevedibile a seconda del
> compilatore adottato e quindi come esempio mi sembra nettamente piu'
> efficace.

*NO*. Il risultato è imprevedibile in ogni caso, anche nel caso
dell'addizione. Come già detto, non c'entra l'operazione eseguita. Ho
già ampiamente spiegato il perché nei messaggi precedenti. Se dici di
essere d'accordo, dovresti averlo capito. Forse fai bene a spiegare
che intendi tu per "codice che funziona egregiamente bene".

GuGu

unread,
Jul 16, 2008, 2:44:51 AM7/16/08
to
> Il risultato è imprevedibile in ogni caso, anche nel caso
> dell'addizione. Come già detto, non c'entra l'operazione eseguita.

Ma scusa: in fase di esecuzione le due funzioni func(i) non restituiscono
comunque due valori corretti?
Dato int i = 0 le due funzioni restituiscono comunque 0 e 1 oppure 1 e 0 o
sbaglio?

Andrea Laforgia

unread,
Jul 16, 2008, 3:55:48 AM7/16/08
to

None. Potrebbe. Ma potrebbe anche non farlo. Il compilator, per
esempio, è libero di individuare una chiamata alla stessa funzione
func con lo stesso parametro in due luoghi diversi della stessa
espressione e quindi limitarsi a invocare la funzione una sola volta e
usare il suo risultato in entrambi i posti. Come già ampiamente detto,
il compilatore è libero di piazzare i sequence point dove gli pare.

GuGu

unread,
Jul 16, 2008, 5:06:01 AM7/16/08
to
> None. Potrebbe. Ma potrebbe anche non farlo. Il compilator, per
> esempio, č libero di individuare una chiamata alla stessa funzione

> func con lo stesso parametro in due luoghi diversi della stessa
> espressione e quindi limitarsi a invocare la funzione una sola volta e
> usare il suo risultato in entrambi i posti.

A caz... allora non avevo proprio capito. Pensavo comunque che le due
funzioni uguali all'interno della stessa espressione venissero *SEMPRE*
chiamate distintamente.
Quindi se io scrivo
int a = MyRnd() * 10 + MyRnd() * 100
Dove MyRndrestituisce un numero casuale da 1 a 10. Che cosa fa il
compilatore? Mi restituisce 110, 220, 330 etc?


> Come gią ampiamente detto, il compilatore č libero di piazzare i sequence
> point dove gli pare.

Oui, questo l'avevo capito! GIURO !


GuGu

unread,
Jul 16, 2008, 5:42:24 AM7/16/08
to
>> Il compilator, per
>> esempio, č libero di individuare una chiamata alla stessa funzione
>> func con lo stesso parametro in due luoghi diversi della stessa
>> espressione e quindi limitarsi a invocare la funzione una sola volta e
>> usare il suo risultato in entrambi i posti.

Scusa ma questa cosa piu' ci penso e meno mi convince...
Ma sei proprio sicuro?
Il compilatore come puo' stabilire che le funzioni che chiamo all'interno
della stessa espressione restituiscono lo stesso valore e quindi limitarsi
ad invocare la funzione una sola volta?
Questo fatto mi sta sconvolgendo le poche cose che sapevo sul C++ !!!!!!!!!
Ho provato a scrivere queste due righe di codice:


GuGu

unread,
Jul 16, 2008, 5:44:07 AM7/16/08
to
"GuGu" <prom...@tiscali.it> ha scritto nel messaggio
news:487dc280$0$18150$4faf...@reader3.news.tin.it...

Mancava il codice!

int& func( int& i ) { return ++i; }

int main(int argc, char* argv[])
{
int B[3] = {10, 20,30};
int i = 0;
int A = B[ func(i) ] + B[ func(i) ];
return 0;
}

Come risultato mi esce 50.
A me 50 sembra giusto.
Ma un altro compilatore: che risultato ti potrebbe dare?
40 o 60 ?


Max M.

unread,
Jul 16, 2008, 6:19:02 AM7/16/08
to
GuGu wrote:
> int& func( int& i ) { return ++i; }
>
> int main(int argc, char* argv[])
> {
> int B[3] = {10, 20,30};
> int i = 0;
> int A = B[ func(i) ] + B[ func(i) ];
> return 0;
> }
>
> Come risultato mi esce 50.
> A me 50 sembra giusto.

Avevo scelto appositamente un esempio del genere, proprio perché
"intuitivamente" il risultato ci sembra ovvio e difficilmente immaginiamo
che un compilatore possa produrre un risultato diverso.

Nondimeno, quel codice viola quella regola dello standard che ho citato
nella mia prima risposta in questo thread. La questione č tutta lě.

Max


Andrea Laforgia

unread,
Jul 16, 2008, 6:58:36 AM7/16/08
to
On 16 Lug, 11:42, "GuGu" <promp...@tiscali.it> wrote:

> Il compilatore come puo' stabilire che le funzioni che chiamo all'interno
> della stessa espressione restituiscono lo stesso valore e quindi limitarsi
> ad invocare la funzione una sola volta?

No, ripensandoci credo - riguardo questo punto specifico - d'aver
detto una cazzata e cioè il compilatore non può arrogarsi il diritto
di ridurre il numero di chiamate, perché non sa in che modo le diverse
chiamate influiranno sul flusso dell'applicazione. Ma la mia cazzata
finisce qui, perché il punto di cui si sta discutendo non è questo.
Quanto si sta dicendo nel thread e che ha ribadito Max col suo esempio
rimane valido: il suo codice viola le regole ed è sbagliato.

Il compilatore comunque potrebbe ragionare come vuole, nel trattare
quelle espressioni e quindi disattendere le aspettative di un
programmatore che immagina vi sia una sequenza di calcolo precisa.

Andrea Laforgia

unread,
Jul 16, 2008, 6:59:36 AM7/16/08
to
On 16 Lug, 11:44, "GuGu" <promp...@tiscali.it> wrote:

> Ma un altro compilatore: che risultato ti potrebbe dare?
> 40 o 60 ?

Non ragionare in base all'esempio specifico, cerca di considerare
l'aspetto generale.

GuGu

unread,
Jul 16, 2008, 9:12:55 AM7/16/08
to
> Nondimeno, quel codice viola quella regola dello standard che ho citato
> nella mia prima risposta in questo thread. La questione č tutta lě.


Si, ma insisto sul fatto che nel tuo esempio la "sequence point" e'
ininfluente proprio perche' hai usato l'operatore + e quindi non vi sono
"side effect." E' come se per sostenere quest'altra regola dello standard
"If an object that has automatic storage duration is not initialized
explicitly, its value is indeterminate." io scrivessi un esempio di questo
tipo:

void foo (int& i) {i = 0;};

int i;
foo (i);

Mi potresbbero obiettare un bel "e chi se ne frega che i non e'
inizializzato?".

Molto meglio un:

void foo (int& i) {i++;};

dove risulta piu' evidente dove sta il problema.

GM

unread,
Jul 16, 2008, 9:35:50 AM7/16/08
to
Max M. ha scritto:

>
> Beh, 3 è tanto "sbagliato" quanto 7.
>
> Ad ogni modo, bisogna tenere comqunque presente che il compilatore non può
> sempre diagnosticare questo tipo di violazioni. Ad esempio, questo codice
>
> int& func( int& i ) { return ++i; }
>
> A = B[ func(i) ] + B[ func(i) ];
>
> non produce alcun warning, ma è tanto sbagliato quanto l'altro.
>
> Max

Non vorrei alimentare una polemica sterile, ma perchè mi spiegate meglio
questo sarebbe sbagliato?
Non mi sembra che violi la regola citata prima. Sbaglio?

E poi per "sbagliato" cosa intendete? UB?

GM

Davide Quack

unread,
Jul 16, 2008, 10:53:25 AM7/16/08
to
Scriveva Andrea Laforgia mercoledì, 16/07/2008:

> No, ripensandoci credo - riguardo questo punto specifico - d'aver
> detto una cazzata e cioè il compilatore non può arrogarsi il diritto
> di ridurre il numero di chiamate, perché non sa in che modo le diverse
> chiamate influiranno sul flusso dell'applicazione.

Secondo me niente di quello che hai detto è scorretto. Se per motivi
suoi l'ottimizzatore decide che una funzione chiamata due volte
ritornerà sempre lo stesso valore, esso potrebbe ottimizzare il codice
eliminando una delle due chiamate e usare una variabile intermedia.

--
Articolo 33 della Costituzione italiana: L'arte e la scienza sono
libere e libero ne è l'insegnamento.
detto qesto: http://www.pluto.it/files/ildp/HOWTO/Coffee/Coffee.html
oppure questo? http://lenr-canr.org/acrobat/DeNinnoAexperiment.pdf


Andrea Laforgia

unread,
Jul 16, 2008, 11:02:59 AM7/16/08
to
On 16 Lug, 16:53, Davide Quack <qu...@tin.it> wrote:

> Secondo me niente di quello che hai detto è scorretto.

Meno male :-)

>Se per motivi
> suoi l'ottimizzatore decide che una funzione chiamata due volte
> ritornerà sempre lo stesso valore, esso potrebbe ottimizzare il codice
> eliminando una delle due chiamate e usare una variabile intermedia.

Sì, ovviamente concordo. Il problema è capire se questa deduzione da
parte del compilatore è fattibile anche nel caso postato da Max.
Quella funzione restituisce il reference ricevuto in input, dopo
averne modificato il valore, quindi il compilatore dovrebbe dedurre
che lo stato della variabile cambiare con due chiamate e che quindi
esse possono essere significative. Un po' troppo avanzato come
ragionamento ma si sa che gli ottimizzatori di oggi sono furbissimi...

Andrea Laforgia

unread,
Jul 16, 2008, 11:14:19 AM7/16/08
to
On 16 Lug, 15:12, "GuGu" <promp...@tiscali.it> wrote:

> Si, ma insisto sul fatto che nel tuo esempio la "sequence point" e'
> ininfluente proprio perche' hai usato l'operatore + e quindi non vi sono
> "side effect."

No GuGu, continui a sbagliarti. Non è ininfluente, dipende tutto da
come il compilatore interpreta il codice. Tu stai ragionando da umano,
secondo una linea precisa: immagini che comunque le due func(i)
vengano chiamate in sequenza e quindi, siccome l'operazione + è
commutativa, la somma dei valori restituiti è costante. Basi questo
ragionamento assumendo che all'uscita di ciascuna func() il valore di
i sia stato già incrementato e questo perché poni le tue "sequence
point" all'interno del calcolo. Il compilatore potrebbe non ragionare
così.
Ti spiego: io compilatore potrei pensare: ok, ciò che importa al
programmatore è che di ritorno vi sia il reference alla variabile e
lui (il programmatore) sa bene che *non* deve far affidamento
sull'avvenuto incremento del valore della variabile, quindi io mi
sento libero di spostare tutti i pre-incrementi a fine espressione, in
un bel sequence-point globale. Quello che accade in questo caso è che
potresti avere, in dipendenza dai compilatori, i seguenti casi:

1) B[0] + B[0] /* il compilatore ha piazzato il sequence-point *dopo*
il calcolo dell'espressione */
2) B[0] + B[1]
3) B[1] + B[0]
4) B[1] + B[1]

Visto che stiamo parlando di un'operazione aritmetica, tralascio
ovviamente il fatto che in C++ gli operatori si possono sovraccaricare
e in quel caso vattelapesca che cosa potrebbe succedere.

(Spero di non aver detto cagate)

Max M.

unread,
Jul 16, 2008, 11:16:50 AM7/16/08
to
GuGu wrote:
>> Nondimeno, quel codice viola quella regola dello standard che ho citato
>> nella mia prima risposta in questo thread. La questione č tutta lě.
>
>
> Si, ma insisto sul fatto che nel tuo esempio la "sequence point" e'
> ininfluente proprio perche' hai usato l'operatore + e quindi non vi sono
> "side effect."

Scusa, ma secondo me la questione č molto semplice: č vero o no che
nell'espressione in questione 'i' viene modificato piů di una volta? Mi
pare di sě. Quindi la regola č violata. Fine della discussione.

Al posto di "func(i)" ci puoi mettere "++i". L'espressione viola sempre la
regola. Perň nel secondo caso GCC č in grado di diagnosticare il possibile
problema e avvertirti, nel primo caso no. Lo scopo del mio esempio era solo
questo.

Max

Davide Quack

unread,
Jul 16, 2008, 11:25:05 AM7/16/08
to
Andrea Laforgia scriveva il 16/07/2008 :

> Il problema è capire se questa deduzione da
> parte del compilatore è fattibile anche nel caso postato da Max.

Come avete già fatto notare il codice è scorretto, quindi perché
preoccuparsi di cosa fa il compilatore o l'ottimizzatore? E' come
chiedersi cosa succede con:

int a = *((int *)0);

succede che con codice simile cerchi rogne.

Max deve capire, oserei dire interiorizzare, il _perché_ quel codice
non è valido. Se non lo capisce adesso la cosa migliore che potrebbe
fare è: staccare il cervello, e ripensarci magari domani a mente
fresca.

GM

unread,
Jul 16, 2008, 11:27:08 AM7/16/08
to
Andrea Laforgia ha scritto:

> On 16 Lug, 15:12, "GuGu" <promp...@tiscali.it> wrote:
>
>> Si, ma insisto sul fatto che nel tuo esempio la "sequence point" e'
>> ininfluente proprio perche' hai usato l'operatore + e quindi non vi sono
>> "side effect."
>
...

> Ti spiego: io compilatore potrei pensare: ok, ciò che importa al
> programmatore è che di ritorno vi sia il reference alla variabile e
> lui (il programmatore) sa bene che *non* deve far affidamento
> sull'avvenuto incremento del valore della variabile, quindi io mi
> sento libero di spostare tutti i pre-incrementi a fine espressione, in
> un bel sequence-point globale.
...

Ecco, siccome non mi avete (Andrea Laforgia e Max M.) risposto più
sotto, intervengo quì:

secondo me state partendo dall'ipotesi (che IMHO è sbagliata) che non
sia definito dove sono i sequence point.
Ma lo std lo definisce al punto 1.9-17 dove se capisco bene dice che ci
sono s.p. sia in entrata sia in uscita dalle funzioni.

Quindi nell'esempio dobbiamo considerare che il fatto che i venga
incrementato prima che la funzione ritorni è garantito.
A questo punto resta U.B. solo l'ordine di valutazione dei due operandi
della somma ma in questo caso il risultato è definito lo stesso per via
della commutatività (ok, se fai overload della somma e la implementi in
modo non commutativo resta UB anche il risultato).

Tutto molto IMHO

GM

GM

unread,
Jul 16, 2008, 11:31:20 AM7/16/08
to
Max M. ha scritto:

> GuGu wrote:
>>> Nondimeno, quel codice viola quella regola dello standard che ho citato
>>> nella mia prima risposta in questo thread. La questione č tutta lě.
>>
>> Si, ma insisto sul fatto che nel tuo esempio la "sequence point" e'
>> ininfluente proprio perche' hai usato l'operatore + e quindi non vi sono
>> "side effect."
>
> Scusa, ma secondo me la questione č molto semplice: č vero o no che
> nell'espressione in questione 'i' viene modificato piů di una volta? Mi
> pare di sě. Quindi la regola č violata. Fine della discussione.
>
E secondo me (vedi altra risposta) ti sbagli perchč la regola parla di +
di una modifica all'interno di due s.p. successivi Ma nel nostro caso la
chiamata a funzione introduce almeno altri 4 s.p. (1 per ogni ingresso e
uno per ogni uscita). Quindi non c'č doppia modifica.


> Al posto di "func(i)" ci puoi mettere "++i". L'espressione viola sempre la
> regola.

In questo caso non c'č la chiamata a funzione e i suoi s.p. quindi hai
ragione.


Almeno questo č quello che capisco io leggendo lo std.

GM

Andrea Laforgia

unread,
Jul 16, 2008, 11:34:35 AM7/16/08
to
On 16 Lug, 17:27, GM <G...@no.spam.it> wrote:

> secondo me state partendo dall'ipotesi (che IMHO è sbagliata) che non
> sia definito dove sono i sequence point.
> Ma lo std lo definisce al punto 1.9-17 dove se capisco bene dice che ci
> sono s.p. sia in entrata sia in uscita dalle funzioni.

Non ho sottomano lo standard e quindi non posso guardare, però credo
il punto sia quello che dice Max e cioè che se in una espressione la
stessa variabile viene modificata più volte, la regola è violata.
Punto. Gli dò pienamente ragione su ciò. Secondo me non si può fare
affidamento sulla commutatività dell'operatore per il fatto che
l'unico contratto che la funzione è tenuta a rispettare col
programmatore è che sia restituito il reference alla variabile. A casa
mi guardo il punto 1.9-17 dello standard.

Andrea Laforgia

unread,
Jul 16, 2008, 11:35:03 AM7/16/08
to
On 16 Lug, 17:25, Davide Quack <qu...@tin.it> wrote:

> Come avete già fatto notare il codice è scorretto, quindi perché
> preoccuparsi di cosa fa il compilatore o l'ottimizzatore?

Concordo.

Andrea Laforgia

unread,
Jul 16, 2008, 11:35:54 AM7/16/08
to
On 16 Lug, 17:16, "Max M." <ed...@maxim.comm2000.it> wrote:

> Scusa, ma secondo me la questione è molto semplice: è vero o no che
> nell'espressione in questione 'i' viene modificato più di una volta? Mi
> pare di sì. Quindi la regola è violata. Fine della discussione.

Sì, è questo il punto e difatti su questo sono assolutamente concorde.
Diciamo che il thread si è aperto via via in sotto-thread che non
c'entravano molto col tema principale, anche per colpa mia :-)

GM

unread,
Jul 16, 2008, 11:41:18 AM7/16/08
to
Andrea Laforgia ha scritto:

Nono, la regola non parla di espressione ma di sequence point:
"Between the previous and next sequence point an object shall have its
stored value modified at most once by the evaluation of an expression.
Furthermore, the prior value shall be accessed only to determine the
value to be stored."

E il punto 1.9-17 dice:
"When calling a function (whether or not the function is inline), there
is a sequence point after the evaluation of all function arguments (if
any) which takes place before execution of any expressions or statements
in the function body. There is also a sequence point after the copying
of a returned value and before the execution of any expressions outside
the function. Several contexts in C++ cause evaluation of a function
call, even though no corresponding function call syntax appears in the
translation unit. [Example: evaluation of a new expression invokes one
or more allocation and constructor functions; see 5.3.4. For another
example, invocation of a conversion function (12.3.2) can arise in
contexts in which no function call syntax appears. —end example] The
sequence points at function-entry and function-exit (as described above)
are features of the function calls as evaluated, whatever the syntax of
the expression that calls the function might be."

GM


Sergio

unread,
Jul 16, 2008, 11:51:09 AM7/16/08
to
Andrea Laforgia wrote:
> On 16 Lug, 17:16, "Max M." <ed...@maxim.comm2000.it> wrote:
>> Scusa, ma secondo me la questione è molto semplice: è vero o no che
>> nell'espressione in questione 'i' viene modificato più di una volta? Mi
>> pare di sì. Quindi la regola è violata. Fine della discussione.
> Sì, è questo il punto e difatti su questo sono assolutamente concorde.
La regola dice:

"Between the previous and next sequence point an object shall have its
stored value modified at most once by the evaluation of an expression.
Furthermore, the prior value shall be accessed only to determine the
value to be stored."
La chiamata di funzione introduce un sequence point.
Nell'espressione in questione i *non* viene modificato e/o acceduto più
di una volta tra due sequence point consecutivi, quindi la regola *non*
viene violata.

Ciao.

Sergio

unread,
Jul 16, 2008, 11:58:18 AM7/16/08
to
GM wrote:
>
> Nono, la regola non parla di espressione ma di sequence point:
Non avevo visto che avevi già risposto.
Quello che dici è corretto, l'espressione in questione non viola la
regola, così come non la viola neppure questa (a parte che non ha alcun
senso):

int i = 1;

if (++i && ++i)
;

perché anche l'operatore && introduce un sequence point.

Ciao.

GuGu

unread,
Jul 16, 2008, 12:05:29 PM7/16/08
to
> io compilatore potrei pensare: ok, ciň che importa al programmatore č che
> di ritorno vi sia il reference

Effettivamente il reference di cui dici e' un dettaglio che ho trascurato.

> quindi io mi sento libero di spostare tutti i pre-incrementi a fine
> espressione, in un bel sequence-point globale.

Questo ragionamento non fa una grinza.
Mi viene solo da pensare che se tu compilatore sei in grado di fare una cosa
del genere allora si che il warning me lo puoi dare.
Tutto questo thread (davvero molto istruttivo per me e ti/vi ringrazio per
le risposte che mi state dando) e' partito da Max che ha postato proprio
questo esempio per dire che il compilatore non poteva sempre diagnosticare
questo tipo di violazioni.
Invece mi stai dicendo che come compilatore potresti essere in grado di
spostare i sequence point addirittura da dentro alla funzione all'esterno
dell'espressione. A questo pero' se non sei in grado di darmi il warning mi
incazzo !!!!! ;-)

> Visto che stiamo parlando di un'operazione aritmetica, tralascio
> ovviamente il fatto che in C++ gli operatori si possono sovraccaricare e
> in quel caso vattelapesca che cosa potrebbe succedere.

Assolutamente corretto.


Andrea Laforgia

unread,
Jul 16, 2008, 12:41:45 PM7/16/08
to
On 16 Lug, 17:58, Sergio <ser...@invalid.invalid> wrote:

> if (++i && ++i)

Aspetta, questo è un altro caso: l'operatore && è uno dei pochi che
determina il flusso delle operazioni: cioè il primo ++i è eseguito
sicuramente prima del secondo. E' per questo che scrivere: if (a > 0
&& b/a == 1) è un'operazione sicura. Comunque ora scappo a casa,
studio e poi rispondo ;-)

Max M.

unread,
Jul 16, 2008, 12:56:22 PM7/16/08
to
GM wrote:
>> Scusa, ma secondo me la questione č molto semplice: č vero o no che
>> nell'espressione in questione 'i' viene modificato piů di una volta? Mi
>> pare di sě. Quindi la regola č violata. Fine della discussione.
>>
> E secondo me (vedi altra risposta) ti sbagli perchč la regola parla di +
> di una modifica all'interno di due s.p. successivi Ma nel nostro caso la
> chiamata a funzione introduce almeno altri 4 s.p. (1 per ogni ingresso e
> uno per ogni uscita). Quindi non c'č doppia modifica.

Sě, hai ragione. Ho detto una sciocchezza. Il fatto che ci sia di mezzo una
chiamata a funzione cambia completamente la situazione.

Max

Max M.

unread,
Jul 16, 2008, 12:58:36 PM7/16/08
to
Sergio wrote:
> GM wrote:
>>
>> Nono, la regola non parla di espressione ma di sequence point:
> Non avevo visto che avevi già risposto.
> Quello che dici è corretto,

Avete ragione. Ho detto una sciocchezza. (Lo ribadisco anche qui, in caso
qualcuno si perda il mio messaggio nell'altro ramo.)

Max

Andrea Laforgia

unread,
Jul 16, 2008, 3:40:34 PM7/16/08
to
On Wed, 16 Jul 2008 17:51:09 +0200, Sergio <ser...@invalid.invalid>
wrote:

>La chiamata di funzione introduce un sequence point.

Indubbiamente.

Lo standard afferma testualmente "When calling a function (whether or


not the function is inline), there is a sequence point after the
evaluation of all function arguments (if any) which takes place before
execution of any expressions or statements in the function body. There
is also a sequence point after the copying of a returned value and
before the execution of any expressions outside the function"

E fin qui ci siamo. Vuol dire che all'atto di ciascuna delle due
chiamate a func() c'è un sequence point prima di entrare nel corpo
della funzione e c'è un sequence point una volta usciti dalla
funzione.

Il che vuole dire che, no, la regola non viene violata.

Cionondimeno, mi chiedevo se il risultato di quell'operazione non sia
ugualmente indeterminato. Mi spiego: visto che non è garantito
l'ordine di entrambe le esecuzioni della funzione func() e che l'unico
contratto che il compilatore è tenuto a rispettare è quello di dare
indietro il reference, potrebbe accadere - domando - che le due
chiamate avvengano entrambe prima della somma e che invece ai due B[]
venga passato lo stesso valore?

int i=0;
Dato A = B[func(i)] + B[func(i)];

potrebbe succedere questo? :

1) i = 0;
2) func(i): 2.1) sequence point
2.2) esecuzione di func();
2.3) sequence point: i = 1;
3) func(i): 3.1) sequence point
3.2) esecuzione di func();
3.3) sequence point: i = 2;
4) A = B[2] + B[2];

E' plausibile o sto dicendo una cazzata?

?manu*

unread,
Jul 16, 2008, 3:52:21 PM7/16/08
to
Davide Quack wrote:
> Come avete già fatto notare il codice è scorretto, quindi perché
> preoccuparsi di cosa fa il compilatore o l'ottimizzatore?

Ma il dubbio è, ammesso che un compilatore abbia una certa libertà nel
decidere come valutare certe espressioni, se per una particolare
espressione succede che qualunque modo "legale" di valutare
l'espressione porta allo stesso risultato, allora posso confidare nel
fatto che il compilatore mi dà QUEL risultato?

Penso che la risposta sia sì.

A questo punto resta da decidere se l'espressione

int& func( int& i ) { return ++i; }

A = B[ func(i) ] + B[ func(i) ];

ha, oppure no, questa proprietà. Io ci ho pensato un po' e devo dire che
non mi è molto chiaro. In effetti non mi è chiaro neanche quale sia
l'effetto (se è definito) di

++i=1;


E.

Andrea Laforgia

unread,
Jul 16, 2008, 4:19:49 PM7/16/08
to
On Wed, 16 Jul 2008 21:52:21 +0200, ?manu*
<pao...@NO.math.unifi.SPAM.it> wrote:

> int& func( int& i ) { return ++i; }
>
> A = B[ func(i) ] + B[ func(i) ];

Il fatto è che secondo me il compilatore è libero di invocare func(i)
per due volte, ma non necessariamente nell'ordine che ci si
aspetterebbe. L'ordine che istintivamente ci si aspetta, nel leggere
quell'espressione é:

1) eseguo func(i)
2) prelevo l'elemento t1 = B[i]
3) eseguo func(i)
4) prelevo l'elemento t2 = B[i]
5) metto in A la somma t1+t2

Credo che il compilatore sia libero di ristabilire l'ordine, senza
pregiudicare il senso (non il risultato) dell'espressione:

1) eseguo func(i)
2) eseguo func(i)
3) prelevo l'elemento t1 = B[i]
4) prelevo l'elemento t2 = B[i]
5) metto in A la somma t1+t2

> ++i=1;

Credo che questa non sia legale per il discorso dei sequence point (ma
è tardi e ho sonno...).

Soviet_Mario

unread,
Jul 16, 2008, 6:41:38 PM7/16/08
to
GM ha scritto:

> Andrea Laforgia ha scritto:
>> On 16 Lug, 15:12, "GuGu" <promp...@tiscali.it> wrote:
>>
>>> Si, ma insisto sul fatto che nel tuo esempio la "sequence point" e'
>>> ininfluente proprio perche' hai usato l'operatore + e quindi non vi sono
>>> "side effect."
>>
> ...
>> Ti spiego: io compilatore potrei pensare: ok, ciò che importa al
>> programmatore è che di ritorno vi sia il reference alla variabile e
>> lui (il programmatore) sa bene che *non* deve far affidamento
>> sull'avvenuto incremento del valore della variabile, quindi io mi
>> sento libero di spostare tutti i pre-incrementi a fine espressione, in
>> un bel sequence-point globale.
> ...
>
> Ecco, siccome non mi avete (Andrea Laforgia e Max M.) risposto più
> sotto, intervengo quì:
>
> secondo me state partendo dall'ipotesi (che IMHO è sbagliata) che non
> sia definito dove sono i sequence point.
> Ma lo std lo definisce al punto 1.9-17 dove se capisco bene dice che ci
> sono s.p. sia in entrata sia in uscita dalle funzioni.

chissà se quanto detto vale anche se la funzione viene
espansa inline ... una funzione simile dovrebbe esserlo
quasi sicuramente. Poi per carità, può essere che il
compilatore tracci il codice espanso inline da sé stesso e
lo differenzi dal restante, collocando coerentemente questi
sequence points, ma io non ho idea

Penso che per il discorso dell'usare una variabile
accessoria per velocizzare la doppia valutazione di una
funzione che esso stima produrre il medesimo valore, ci
possa essere solo l'escamotage di dichiarare VOLATILE quel
parametro. E' il modo di informare il compilatore di non
fare assunzioni di alcun genere su quella variabile e
ricaricarla sempre e aggiornare sempre il valore in ram a
ogni lettura o scrittura, dicendogli che il suddetto valore
è soggetto a modifiche che egli non può prevedere.
Però se devo essere onesto non so manco se sia previsto
l'attributo volatile per i tipi reference ... forse si, boh

Ovviamente non credo che accrocchiare e lottare strenuamente
per stabilizzare un codice indefinito a bruta forza sia
l'approccio giusto, se standardizzare e riodrinare è il tuo
scopo.
Se invece scrivi codice per te stesso come facevo io, puoi
fregartene e basta che funzioni colla versione pippo del
compilatore pluto. Lì lo sai te se è una prospettiva adatta.

>
> Quindi nell'esempio dobbiamo considerare che il fatto che i venga
> incrementato prima che la funzione ritorni è garantito.

verifica comunque che ciò tenga anche per le funzioni
espanse inline.
ciao
Soviet

Soviet_Mario

unread,
Jul 16, 2008, 6:44:11 PM7/16/08
to
GM ha scritto:

> Andrea Laforgia ha scritto:
>> On 16 Lug, 17:27, GM <G...@no.spam.it> wrote:
>>
>>> secondo me state partendo dall'ipotesi (che IMHO è sbagliata) che non
>>> sia definito dove sono i sequence point.
>>> Ma lo std lo definisce al punto 1.9-17 dove se capisco bene dice che ci
>>> sono s.p. sia in entrata sia in uscita dalle funzioni.
>>
>> Non ho sottomano lo standard e quindi non posso guardare, però credo
>> il punto sia quello che dice Max e cioè che se in una espressione la
>> stessa variabile viene modificata più volte, la regola è violata.
>> Punto. Gli dò pienamente ragione su ciò. Secondo me non si può fare
>> affidamento sulla commutatività dell'operatore per il fatto che
>> l'unico contratto che la funzione è tenuta a rispettare col
>> programmatore è che sia restituito il reference alla variabile. A casa
>> mi guardo il punto 1.9-17 dello standard.
>>
>
> Nono, la regola non parla di espressione ma di sequence point:
> "Between the previous and next sequence point an object shall have its
> stored value modified at most once by the evaluation of an expression.
> Furthermore, the prior value shall be accessed only to determine the
> value to be stored."
>
> E il punto 1.9-17 dice:
> "When calling a function (whether or not the function is inline),

ti chiedo scusa per un intervento che ho fatto senza ancora
avere letto questo punto. Il mio dubbio sull'espansione
inline i è rivelato ingenuo : ovviamente avevano pensato a ciò
riciao
Soviet_Mario

CUT ALL

Sergio

unread,
Jul 16, 2008, 7:30:08 PM7/16/08
to
Andrea Laforgia wrote:
>
> Cionondimeno, mi chiedevo se il risultato di quell'operazione non sia
> ugualmente indeterminato. Mi spiego: visto che non è garantito
> l'ordine di entrambe le esecuzioni della funzione func() e che l'unico
> contratto che il compilatore è tenuto a rispettare è quello di dare
> indietro il reference, potrebbe accadere - domando - che le due
> chiamate avvengano entrambe prima della somma e che invece ai due B[]
> venga passato lo stesso valore?
L'ordine di valutazione è indeterminato, ma è garantito che non ci siano
"incroci" di esecuzione. Mi spiego meglio (spero) con un esempio:

int f_a(int i) { cout "a"; return i; }
int f_b(int i) { cout "b"; return i; }
int f_c(int i) { cout "c"; return i; }
int f_d(int i) { cout "d"; return i; }
int f_e(int i) { cout "e"; return i; }
int f_f(int i) { cout "f"; return i; }
...

int a = f_a( f_b(0) + f_c(0) ) + f_d( f_e(0) + f_f(0) );

La valutaziona parte da f_a o da f_d e prosegue nella valutazione dei
rispettivi parametri, quindi f_b *e* f_c (in ordine non definito) se si
è iniziato da f_a oppure f_e *e* f_f (in ordine non definito) se si è
iniziato da f_d

Per farla breve i possibili output dell'espressione di cui sopra sono:

bcaefd
bcafed
cbaefd
cbafed
efdbca
efdcba
fedbca
fedcba

Non sono possibili altri output.

> int i=0;
> Dato A = B[func(i)] + B[func(i)];
>
> potrebbe succedere questo? :

[...]


> 4) A = B[2] + B[2];
>
> E' plausibile o sto dicendo una cazzata?

Direi che per quanto sopra ciò non è possibile.

Ciao.

Sergio

unread,
Jul 16, 2008, 7:40:54 PM7/16/08
to
?manu* wrote:
>
> Ma il dubbio è, ammesso che un compilatore abbia una certa libertà nel
> decidere come valutare certe espressioni, se per una particolare
> espressione succede che qualunque modo "legale" di valutare
> l'espressione porta allo stesso risultato, allora posso confidare nel
> fatto che il compilatore mi dà QUEL risultato?
Il compilatore ha una certa libertà, ma è anche soggetto a dei vincoli.
Ci sono alcuni operatori (&& , (virgola) || ? (operatore ternario) e
forse altri che al momento non mi vengono in mente) che impongono un
ordine di valutazione (e non solo).
Nel caso debba valutare due o più espressioni senza essere soggetto ai
vincoli di cui sopra ha la libertà di iniziare la valutazione
dall'espressione che "preferisce", ma ha il vincolo di doverla valutare
completamente prima di iniziare la valutazione dell'altra espressione (o
delle altre).

>
> In effetti non mi è chiaro neanche quale sia
> l'effetto (se è definito) di
>
> ++i=1;

No, non lo è perché viola la regola postata da MaxM (due assegnamenti
alla stessa variabile all'interno di un singolo sequence point).
Da notare che neppure questa è legale:
int a = 1;
int b = ++a + a;

Perché viola la seconda parte della regola in questione.

Ciao.

GuGu

unread,
Jul 17, 2008, 2:17:40 AM7/17/08
to
> L'ordine di valutazione è indeterminato, ma è garantito che non ci siano
> "incroci" di esecuzione.

Qundi nello standard non e' previsto un ordine di esecuzione per gli
operatori anche se ci sono dei SP?
Dove posso reperire questo standard online per andarmelo a leggere?

Davide Quack

unread,
Jul 17, 2008, 3:48:27 AM7/17/08
to
Sembra che Andrea Laforgia abbia detto :

> Credo che il compilatore sia libero di ristabilire l'ordine, senza
> pregiudicare il senso (non il risultato) dell'espressione:

Un esempio che giudico perfetto. Il punto è tutto lì.

Se non fosse permesso all'ottimizzatore di fare questo tanto varrebbe
eseguire il codice C++ come pcode dentro una virtual machine.

Andrea Laforgia

unread,
Jul 17, 2008, 4:31:55 AM7/17/08
to
On 17 Lug, 01:30, Sergio <ser...@invalid.invalid> wrote:

> L'ordine di valutazione è indeterminato, ma è garantito che non ci siano
>   "incroci" di esecuzione. Mi spiego meglio (spero) con un esempio:

<...>
> int a = f_a( f_b(0) + f_c(0) ) + f_d( f_e(0) + f_f(0) );

<...>


> Non sono possibili altri output.

Ok, però in questo esempio si sta usando sempre l'invocazione di
funzioni, mentre nell'altro esempio è cruciale l'accesso all'array e
quindi l'utilizzo dei valori restituiti come indici.
Nel tuo esempio, è chiaro che se non sono state invocate prima f_b e
f_c non è possibile invocare f_a (sono i suoi argomenti). Idem per f_e
e f_f rispetto a f_d, e comunque l'ordine di esecuzione tra f_a e f_d
non è definito, giustamente. Ciò non toglie che nell'esempio di Max,
il calcolo dei risultati delle due espressioni è indipendente e quindi
il compilatore potrebbe organizzare il codice come vuole (almeno
credo). Se spostasse i due calcoli *prima* del loro utilizzo come
indici dell'array, finirebbe per usare lo stesso indice per il primo e
il secondo B[]...

Andrea Laforgia

unread,
Jul 17, 2008, 4:33:33 AM7/17/08
to
On 17 Lug, 08:17, "GuGu" <promp...@tiscali.it> wrote:

> Qundi nello standard non e' previsto un ordine di esecuzione per gli
> operatori anche se ci sono dei SP?

Sì, esiste ovviamente la precedenza degli operatori (le somme vengono
calcolate dopo le moltiplicazioni e le parentesi introducono dei
passaggi obbligatori) però non è definito l'ordine di valutazione
delle funzioni.

> Dove posso reperire questo standard online per andarmelo a leggere?

Lo standard ISO è acquistabile on-line. Non esistono versioni gratuite
AFAIK.

GuGu

unread,
Jul 17, 2008, 5:03:21 AM7/17/08
to
> Lo standard ISO è acquistabile on-line. Non esistono versioni gratuite

Perdona la mia pigrizia, mi sai dare un link dove posso acquistarlo?
Credo che tra le altre cose non sarebbe male che io e il mio collega ci
andiamo a rileggere questo prima di tutto.


Andrea Laforgia

unread,
Jul 17, 2008, 5:42:55 AM7/17/08
to
On 17 Lug, 11:03, "GuGu" <promp...@tiscali.it> wrote:

> Perdona la mia pigrizia, mi sai dare un link dove posso acquistarlo?
> Credo che tra le altre cose non sarebbe male che io e il mio collega ci
> andiamo a rileggere questo prima di tutto.

Prova a guardare qui:
http://webstore.ansi.org/FindStandards.aspx?SearchString=C%2b%2b&SearchOption=1&PageNum=0

Comunque considera che la lettura dello standard non è agevolissima.
Probabilmente trovi dei "rationale" in giro (anche a pagamento) che
spiegano meglio le questioni. Questo (che non conosco) tanto per fare
un esempio:

http://www.amazon.co.uk/ANSI-ISO-Professional-Programmers-Handbook/dp/0789720221/ref=sr_1_1?ie=UTF8&s=books&qid=1216287749&sr=8-1

Sergio

unread,
Jul 17, 2008, 6:23:01 AM7/17/08
to
Andrea Laforgia wrote:
>
> Ok, però in questo esempio si sta usando sempre l'invocazione di
> funzioni, mentre nell'altro esempio è cruciale l'accesso all'array e
> quindi l'utilizzo dei valori restituiti come indici.
Hai perfettamente ragione, chissà perché stavo pensando esclusivamente
all'overloading del "subscription operator" (che essendo una funzione
introdurrebbe un sequence point).
Essendo B un array l'espressione

int A = B[ func(i) ] + B[ func(i) ];

diventerebbe

int A = *(B + func(i)) + *(B + func(i));

ed in effetti non credo questa ponga alcun vincolo al compilatore.

Ciao.

GuGu

unread,
Jul 17, 2008, 9:51:10 AM7/17/08
to

Andrea Laforgia

unread,
Jul 17, 2008, 2:47:28 PM7/17/08
to
On Thu, 17 Jul 2008 15:51:10 +0200, "GuGu" <prom...@tiscali.it>
wrote:

Già, però non ha proprio un aspetto legale :-)

GuGu

unread,
Jul 18, 2008, 3:16:13 AM7/18/08
to
"Andrea Laforgia" <a.laf...@andrealaforgia.it.invalid> ha scritto nel
messaggio news:it4v749tqcqlma6t5...@4ax.com...

> On Thu, 17 Jul 2008 15:51:10 +0200, "GuGu" <prom...@tiscali.it>
> wrote:
>
>>http://www.comms.scitech.susx.ac.uk/fft/programming/ANSI-ISOCppProfessionalProgrammersHandbook.pdf
>>
>>
>>sembrerebbe proprio lui.
>
> Gią, perņ non ha proprio un aspetto legale :-)


Si, l'ho lasciato perdere e ho comprato il libro (che tristezza ... si trova
usato a 14 sterline...)

0 new messages