[Para el registro, he editado esta respuesta bastante significativamente desde que fue aceptada y votada. Sin embargo, todavía dice básicamente las mismas cosas.]
Este código es profundamente, quizás deliberadamente, confuso. Contiene una instancia estrechamente evitada del comportamiento temible indefinido . Es básicamente imposible determinar si la persona que formuló esta pregunta era muy, muy inteligente o muy, muy estúpida. Y la "lección" que este código puede pretender enseñar o cuestionar sobre usted, es decir, que el operador unario plus no hace mucho, ciertamente no es lo suficientemente importante como para merecer este tipo de dirección subversiva.
Hay dos aspectos confusos del código, la extraña condición:
while(+(+k--)!=0)
y la declaración demente que controla:
k=k++;
Voy a cubrir la segunda parte primero.
Si tiene una variable como kesa que desea incrementar en 1, C le proporciona no una, ni dos, ni tres, sino cuatro formas diferentes de hacerlo:
k = k + 1
k += 1
++k
k++
A pesar de esta recompensa (o quizás por eso), algunos programadores se confunden y emiten contorsiones como
k = k++;
Si no puede averiguar qué se supone que debe hacer, no se preocupe: nadie puede hacerlo. Esta expresión contiene dos intentos diferentes de alterar kel valor (la k =parte y la k++parte), y debido a que no hay una regla en C para decir cuál de las modificaciones intentadas "gana", una expresión como esta está formalmente indefinida , lo que significa no solo eso no tiene un significado definido, pero que todo el programa que lo contiene es sospechoso.
Ahora, si observa con mucho cuidado, verá que en este programa en particular, la línea en k = k++realidad no se ejecuta, porque (como estamos a punto de ver) la condición de control es inicialmente falsa, por lo que el ciclo se ejecuta 0 veces . Por lo que este programa en particular no podría en realidad ser indefinido - pero sigue siendo confuso patológicamente.
Consulte también estas respuestas SO canónicas a todas las preguntas relacionadas con el comportamiento indefinido de este tipo.
Pero no preguntaste sobre el k=k++papel. Preguntaste sobre la primera parte confusa, la +(+k--)!=0condición. Esto se ve extraño, porque es extraño. Nadie jamás jamás escribiría dicho código en un programa real. Entonces no hay razón para aprender cómo entenderlo. (Sí, es cierto, explorar los límites de un sistema puede ayudarlo a aprender sobre sus puntos finos, pero en mi libro hay una línea bastante clara entre exploraciones imaginativas y sugerentes versus exploraciones malintencionadas y abusivas, y esta expresión es muy clara en el lado equivocado de esa línea.)
De todos modos, examinemos +(+k--)!=0. (Y después de hacerlo, olvidémonos de todo). Cualquier expresión como esta debe entenderse de adentro hacia afuera. Supongo que sabes qué
k--
hace. Toma kel valor actual y lo "devuelve" al resto de la expresión, y disminuye más o menos simultáneamente k, es decir, almacena la cantidad k-1nuevamente k.
Pero entonces, ¿qué hace el +? Esto es unario más, no binario más. Es como el unario menos. Sabes que el binario menos hace resta: la expresión
a - b
resta b de a. Y sabes que el unario menos niega las cosas: la expresión
-a
te da el negativo de a. Lo que +hace unario es ... básicamente nada. +ale da ael valor, después de cambiar los valores positivos a valores positivos y negativos a negativos. Entonces la expresión
+k--
te da lo que sea que te haya k--dado, es decir, kel viejo valor.
Pero no hemos terminado, porque tenemos
+(+k--)
Esto solo toma lo que +k--te dio, y se aplica +de nuevo a él. Entonces te da lo que te +k--dio, que fue lo que k--te dio, que era kel valor anterior.
Entonces, al final, la condición
while(+(+k--)!=0)
hace exactamente lo mismo que la condición mucho más común
while(k-- != 0)
habría hecho. (También hace lo mismo que la condición de aspecto aún más complicado while(+(+(+(+k--)))!=0)hubiera hecho. Y esos paréntesis no son realmente necesarios; también hace lo mismo que while(+ + + +k--!=0)hubiera hecho).
Incluso averiguar cuál es la condición "normal"
while(k-- != 0)
hace es un poco complicado. Hay dos cosas que suceden en este ciclo: a medida que el ciclo se ejecuta potencialmente varias veces, vamos a:
- seguir haciendo
k--, para hacer kcada vez más pequeño, pero también
- sigue haciendo el cuerpo del bucle, lo que sea que haga.
Pero hacemos la k--parte de inmediato, antes (o en el proceso de) decidir si hacer otro viaje a través del ciclo. Y recuerde que k--"devuelve" el valor anterior de k, antes de disminuirlo. En este programa, el valor inicial de kes 0. Por k--lo tanto, va a "devolver" el valor anterior 0, luego actualizar ka -1. Pero el resto de la condición es != 0, pero como acabamos de ver, la primera vez que probamos la condición, obtuvimos un 0. Así que no haremos ningún viaje a través del ciclo, por lo que no intentaremos ejecutar el declaración problemática k=k++en absoluto.
En otras palabras, en este ciclo particular, aunque dije que "están ocurriendo dos cosas", resulta que la cosa 1 sucede una vez, pero la cosa 2 ocurre cero veces.
En cualquier caso, espero que ahora esté suficientemente claro por qué esta pobre excusa para un programa termina imprimiendo -1 como el valor final de k. Normalmente, no me gusta responder preguntas de preguntas como esta, se siente como hacer trampa, pero en este caso, dado que estoy tan en desacuerdo con todo el punto del ejercicio, no me importa.