cout vs printf – ordine di esecuzione

Possibile duplicato:
Compilatori e ordine delle argomentazioni di valutazione in C ++
cout << ordine di chiamata alle funzioni che stampa?

  1. Questo:

    int k=3; printf("%d %d %d",k++,k,++k); 

    Fornisce l’output come 4 4 4 perché vengono inseriti nello stack come:

     %d%d%d 4 -- for k++ 4 --for k 4 --for ++k 

    Destra?

  2. Questo:

     int k = 3; cout << k++ << k << ++k; 

    In realtà è ripetuto chiamate di funzione, quindi è equivalente a:

     ( ( (cout << k++) << k) << ++k); 

    Quindi, suppongo che prima di tutto k++ allora k e poi ++k devono essere sempre eseguiti in questo ordine, giusto? Credo che una chiamata di funzione sia un punto di sequenza, ma gli output variano a seconda delle implementazioni. Perché è così?

Questo non è definito perché non esiste un punto di sequenza tra il, nell’istruzione printf. Senza un punto di sequenza il compilatore è libero di ordinare le scritture nella posizione di memoria k come vuole.

Ora ti starai chiedendo ‘che diavolo è un punto seqeunce’ e perché è rilevante? Fondamentalmente un punto di sequenza è un punto nel codice in cui la posizione di memoria in questione, in questo caso k è stata modificata al massimo una volta. C’è una descrizione più completa qui: https://isocpp.org/wiki/faq/misc-technical-issues#double-mod-betw-seq-pt

Come puoi vedere dalle FAQ, il , nel printf non introduce un punto di sequenza.

Nel caso di cout questo è diverso perché ci sono 3 chiamate di funzione operator >> . Una chiamata di funzione introduce un punto di sequenza, pertanto le modifiche alla posizione di memoria k hanno un ordine definito. Comunque (e questo era un punto che mi mancava ma Cubbi lo faceva notare) poiché C / C ++ non definisce l’ordine di valutazione degli argomenti di funzione quegli argomenti, anche se sono funzioni, possono essere valutati in qualsiasi ordine definito dal compilatore. Quindi nell’espressione:

f(h(), g())

Se h () o g () viene valutato per primo non è definito: http://www.stroustrup.com/bs_faq2.html#undefined . Quindi questo è il motivo per cui anche nel caso di cout si ottengono risultati diversi da compilatori diversi, fondamentalmente perché il cout << k++ << k << ++k traduce in cout.operator<<(k++).operator<<(k).operator(++k) che è effettivamente un'espressione come questa: f(h(g(cout, k++), k), ++k) e ogni argomento di funzione viene valutato in un ordine non specificato.

L’ordine di valutazione degli argomenti non è specificato dagli standard. Ciò significa che può accadere in qualsiasi ordine voglia l’implementazione.

Hai risposte che coprono la chiamata a printf ma ti stai anche chiedendo perché l’output cout varia tra i compilatori.

Hai ragione a dire che è equivalente a

 ( ( (cout< 

ora, per valutare quell'espressione e ottenere il suo risultato, il compilatore deve valutare il più a fondo << . Prima di poter chiamare la funzione a << , i suoi due operandi ( (cout< e ++k devono essere valutati. E queste due valutazioni possono avvenire in qualsiasi ordine, o anche simultaneamente (i compilatori spesso intercalano le istruzioni della cpu da due rami indipendenti di codice (come il compilatore pensa) e poiché la valutazione di entrambe le espressioni implica la scrittura in k , il comportamento non è definito nel caso del cout pure.

In realtà, sia printf sia cout << sono chiamate alle funzioni, e C ++ e C non definiscono un ordine di valutazione per gli argomenti. Quindi il risultato per questi casi di test varia dal compilatore al compilatore, dal momento che la sua implementazione è stata definita.