2015-09-30 19 views
5

Qual è il valore di ritorno di f (p, p), se il valore di p è inizializzato su 5 prima della chiamata? Si noti che il primo parametro è passato per riferimento, mentre il secondo parametro viene passato per valore.È un comportamento non definito nel codice specificato?

int f (int &x, int c) { 
     c = c - 1; 
     if (c==0) return 1; 
     x = x + 1; 
     return f(x,c) * x; 
} 

Le opzioni sono:


cerco di spiegare:


In questo codice, ci saranno quattro chiamate ricorsive con parametri (6,4), (7,3), (8,2) e (9,1). L'ultima chiamata restituisce 1. Ma a causa del passaggio per riferimento, x in tutte le precedenti funzioni è ora 9. Quindi, il valore restituito da f (p, p) sarà 9 * 9 * 9 * 9 * 1 = 6561.


Questa domanda proviene dal concorso GATE, (see Q.no.-42). Il tasto di risposta è dato da GATE "Segni a tutti" (significa che non c'è alcuna opzione corretta) key set-C, Q.no.-42. Somewhere ha spiegato come:

In GATE 2013 i marchi sono stati assegnati a tutti come lo stesso codice in C/C++ produce un comportamento non definito. Questo perché * non è un punto di sequenza in C/C++. Il codice corretto deve sostituire

return f(x,c) * x; 

con

res = f(x,c); 
return res * x; 

Ma il codice data funziona bene. La chiave di GATE è sbagliata? O è davvero l'errore con la domanda?

+2

Una delle cose che possono accadere se si attraversa la strada senza guardare in entrambi i modi è che si arriva dall'altra parte in modo sicuro. Ma è un errore * prevedere * che una persona che attraversa la strada senza guardare in entrambi i modi lo farà passare dall'altra parte in modo sicuro. –

+0

Simile all'ambiguità del punto di sequenza, comportamento non definito?] (Http://stackoverflow.com/q/29513572/1708801) –

risposta

14
return f(x,c) * x; 

Il risultato di questa operazione dipende dall'ordine in cui vengono valutate le due cose. Poiché non è possibile prevedere l'ordine in cui verranno valutati, non è possibile prevedere il risultato di questa operazione.

+0

signore, perché funziona bene qui [questo codice] (http://cpp.sh/8m6y) –

+5

@ user4791206 Cosa intendi per "funziona bene"? Dal momento che non puoi prevedere cosa farà, perché diresti cosa sta succedendo sta funzionando bene? Qualcuno che ha predetto che avrebbe valutato nell'altro ordine non direbbe che ha funzionato bene, vero? –

+0

Mezzi, il problema dell'ordine di valutazione è un comportamento non definito [I-read] (http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points)? –

9

C++ 03 Capitolo 5:

Salvo quando diversamente indicato, l'ordine di valutazione degli operandi dei singoli operatori e sottoespressioni dei singoli espressioni, e l'ordine in cui gli effetti collaterali si svolgono, non è specificato.

Quindi, nel caso della f(x,c) * x, l'ordine di valutazione degli operandi non è specificato, il che significa che non è possibile sapere se l'operando a sinistra oa destra otterrà valutata per prima.

Il codice ha comportamento non specificato, il che significa che si comporterà in un determinato modo definito che è noto solo al compilatore.Il programmatore non può sapere cosa farà il codice, solo che valuterà prima l'operando di sinistra o prima l'operando di destra. Il compilatore può persino modificare l'ordine di valutazione caso per caso, a scopo di ottimizzazione.

Se l'ordine di valutazione è importante, è necessario riscrivere il codice. Il codice che si basa su un comportamento non specificato è sempre un bug, probabilmente piuttosto insignificante, che non si presenterà immediatamente.

Un comportamento non specificato è diverso dal comportamento non definito, il che significherebbe che qualsiasi cosa potrebbe accadere, incluso il programma che va in tilt o si blocca.

+2

Come nota a margine, lo stesso testo è diverso in C++ 11 ma ha lo stesso significato. Penso che C++ 11 (e C11) abbia reso il testo molto più difficile da capire, perché sto citando una versione precedente dello standard. – Lundin

+0

Grazie signore, l'ho capito. –

+0

In generale, "comportamento non specificato" non significa che un programmatore non può sapere cosa farà il codice - semplicemente che il programmatore non può sapere in nessun caso quale dei possibili comportamenti che un compilatore selezionerà. Se tutte le possibili combinazioni di comportamento del compilatore soddisfino i requisiti del programmatore, allora un programmatore avrebbe il diritto di aspettarsi che il programma funzioni correttamente. Non c'è nulla di sbagliato nel codice che si basa su un compilatore che sceglie in modo non specificato tra le azioni definite, a patto che funzioni con qualsiasi selezione effettuata dal compilatore. – supercat

Problemi correlati