[Per la cronaca, ho modificato questa risposta in modo molto significativo da quando è stata accettata e votata. Dice comunque sostanzialmente le stesse cose.]
Questo codice è profondamente, forse deliberatamente, confuso. Contiene un'istanza ristretta del comportamento terrificante non definito . È fondamentalmente impossibile determinare se la persona che ha costruito questa domanda fosse molto, molto intelligente o molto, molto stupida. E la "lezione" di questo codice potrebbe pretendere di insegnarti o interrogarti - vale a dire che l'operatore unario plus non fa molto - non è certamente abbastanza importante da meritare questo tipo di sovversione errata.
Esistono due aspetti confusi del codice, la strana condizione:
while(+(+k--)!=0)
e la dichiarazione demente che controlla:
k=k++;
Coprirò prima la seconda parte.
Se hai una variabile come kquella che vuoi incrementare di 1, C non ti dà uno, non due, non tre, ma quattro modi diversi per farlo:
k = k + 1
k += 1
++k
k++
Nonostante questa generosità (o forse per questo), alcuni programmatori si confondono e tossiscono contorsioni come
k = k++;
Se non riesci a capire cosa dovrebbe fare, non preoccuparti: nessuno può. Questa espressione contiene due diversi tentativi di alterare kil valore (la k =parte e la k++parte) e poiché in C non esiste alcuna regola per dire quale delle tentate modifiche "vince", un'espressione come questa è formalmente indefinita , nel senso che non solo non ha un significato definito, ma l'intero programma che lo contiene è sospetto.
Ora, se guardi con molta attenzione, vedrai che in questo particolare programma, la linea k = k++non viene effettivamente eseguita, perché (come stiamo per vedere) la condizione di controllo è inizialmente falsa, quindi il ciclo viene eseguito 0 volte . Così questo particolare programma potrebbe non effettivamente essere indefinito - ma è ancora patologicamente confusione.
Vedi anche queste risposte SO canoniche a tutte le domande relative a comportamenti indefiniti di questo tipo.
Ma non hai chiesto la k=k++parte. Hai chiesto della prima parte confusa, la +(+k--)!=0condizione. Sembra strano, perché è strano. Nessuno scriverebbe mai un codice del genere in un vero programma. Quindi non c'è motivo di imparare a capirlo. (Sì, è vero, esplorare i confini di un sistema può aiutarti a conoscere i suoi punti positivi, ma c'è una linea abbastanza chiara nel mio libro tra esplorazioni fantasiose e stimolanti rispetto a esplorazioni sconclusionate e offensive, e questa espressione è molto chiara il lato sbagliato di quella linea.)
Comunque, esaminiamo +(+k--)!=0. (E dopo averlo fatto, dimentichiamoci di tutto.) Qualsiasi espressione come questa deve essere capita dall'interno. Presumo che tu sappia cosa
k--
lo fa. Prende kil valore corrente e lo "restituisce" al resto dell'espressione e contemporaneamente diminuisce più o meno k, ovvero immagazzina la quantità k-1in k.
Ma allora cosa fa +? Questo è un plus unario , non un plus binario. È proprio come meno unario. Sai che il meno binario fa sottrazione: l'espressione
a - b
sottrae b da a. E sai che meno unario nega le cose: l'espressione
-a
ti dà il negativo di a. Ciò che +fa unario è ... praticamente nulla. +ati dà avalore, dopo aver cambiato i valori positivi in positivi e negativi in negativi. Quindi l'espressione
+k--
ti dà tutto ciò che ti ha k--dato, cioè kil vecchio valore.
Ma non abbiamo finito, perché abbiamo
+(+k--)
Questo prende tutto ciò che +k--ti ha dato e si applica +di nuovo unario . Quindi ti dà tutto ciò che +k--ti ha dato, che era qualunque cosak-- ti abbia dato, che era kil vecchio valore.
Quindi, alla fine, la condizione
while(+(+k--)!=0)
fa esattamente la stessa cosa della condizione molto più ordinaria
while(k-- != 0)
avrebbe fatto. (Fa anche la stessa cosa della condizione ancora più complicatawhile(+(+(+(+k--)))!=0) avrebbe fatto la . E quelle parentesi non sono davvero necessarie; fa anche la stessa cosa che while(+ + + +k--!=0)avrebbe fatto.)
Anche capire quale sia la condizione "normale"
while(k-- != 0)
fa è un po 'complicato. Ci sono due cose che succedono in questo ciclo: Poiché il ciclo viene eseguito potenzialmente più volte, stiamo per:
- continuare a fare
k-- , per renderlo sempre kpiù piccolo, ma anche
- continua a fare il corpo del ciclo, qualunque cosa faccia.
Ma facciamo subito la k--parte, prima (o in procinto di) decidere se fare un altro viaggio nel giro. E ricorda che k--"restituisce" il vecchio valore di k, prima di ridurlo. In questo programma, il valore iniziale di kè 0. Quindi k--"restituirà" il vecchio valore 0, quindi aggiorna ka -1. Ma poi il resto della condizione è != 0- ma come abbiamo appena visto, la prima volta che abbiamo testato la condizione, abbiamo ottenuto uno 0. Quindi non faremo alcun viaggio attraverso il ciclo, quindi non tenteremo di eseguire il dichiarazione problematica k=k++a tutti.
In altre parole, in questo particolare ciclo, anche se ho detto che "ci sono due cose che succedono", si scopre che la cosa 1 accade una volta, ma la cosa 2 accade zero volte.
Ad ogni modo, spero che ora sia sufficientemente chiaro il motivo per cui questa scusa scusa per un programma finisce per stampare -1 come valore finale di k. Normalmente, non mi piace rispondere a domande del quiz come questa - sembra imbrogliare - ma in questo caso, dal momento che sono così in disaccordo con tutto il punto dell'esercizio, non mi dispiace.