[Para constar, editei esta resposta consideravelmente desde que ela foi aceita e votada. No entanto, ainda diz basicamente as mesmas coisas.]
Esse código é profundamente, talvez deliberadamente, confuso. Ele contém uma instância estritamente evitada do comportamento indefinido do pavor . É basicamente impossível determinar se a pessoa que construiu essa pergunta estava sendo muito, muito inteligente ou muito, muito estúpida. E a "lição" que esse código pretende ensinar ou questionar sobre você - a saber, que o operador unário plus não faz muito - certamente não é importante o suficiente para merecer esse tipo de desvio subversivo.
Existem dois aspectos confusos do código, a condição estranha:
while(+(+k--)!=0)
e a declaração demente que controla:
k=k++;
Vou cobrir a segunda parte primeiro.
Se você tem uma variável como k
essa que deseja incrementar em 1, C fornece não uma, não duas, três, mas quatro maneiras diferentes de fazer isso:
k = k + 1
k += 1
++k
k++
Apesar dessa recompensa (ou talvez por causa disso), alguns programadores ficam confusos e expulsam contorções como
k = k++;
Se você não conseguir descobrir o que isso deve fazer, não se preocupe: ninguém pode. Essa expressão contém duas tentativas diferentes de alterar k
o valor (a k =
parte e a k++
parte) e, como não há regra em C para dizer qual das modificações tentadas "vence", uma expressão como essa é formalmente indefinida , significando não apenas que ele tem nenhum significado definido, mas que todo o programa que o contém é suspeito.
Agora, se você olhar com muito cuidado, verá que neste programa em particular, a linha k = k++
não é realmente executada, porque (como estamos prestes a ver) a condição de controle é inicialmente falsa, então o loop é executado 0 vezes . Portanto, este programa em particular não pode realmente ser indefinido - mas ainda é patologicamente confuso.
Veja também essas respostas canônicas de SO a todas as perguntas relacionadas a Comportamento indefinido desse tipo.
Mas você não perguntou sobre o k=k++
papel. Você perguntou sobre a primeira parte confusa, a +(+k--)!=0
condição. Isso parece estranho, porque é estranho. Ninguém jamais escreveria esse código em um programa real. Portanto, não há razão para aprender a entender. (Sim, é verdade, explorar os limites de um sistema pode ajudá-lo a aprender sobre seus pontos positivos, mas há uma linha bastante clara em meu livro entre explorações imaginativas e instigantes e explorações abusivas e idiotas, e essa expressão está muito clara. o lado errado dessa linha.)
Enfim, vamos examinar +(+k--)!=0
. (E depois disso, vamos esquecer tudo.) Qualquer expressão como essa deve ser entendida de dentro para fora. Eu presumo que você sabe o que
k--
faz. Ele pega k
o valor atual e o "retorna" para o restante da expressão e diminui mais ou menos simultaneamente k
, ou seja, armazena a quantidade k-1
novamente k
.
Mas então o que +
faz? Isso é mais unário , e não binário. É como menos unário. Você sabe que binário menos subtrai: a expressão
a - b
subtrai b de a. E você sabe que menos unário nega as coisas: a expressão
-a
dá a você o negativo de a. O +
que é unário é ... basicamente nada. +a
fornece a
o valor de você , depois de alterar valores positivos para positivos e negativos para negativos. Então a expressão
+k--
dá a você o que k--
lhe deu, ou seja, k
o antigo valor.
Mas não terminamos, porque temos
+(+k--)
Isso apenas pega o que +k--
lhe deu e se aplica unicamente +
a ele novamente. Então isso lhe dá o que +k--
lhe deu, o que lhe k--
deu, que era k
o antigo valor.
Então, no final, a condição
while(+(+k--)!=0)
faz exatamente a mesma coisa que a condição muito mais comum
while(k-- != 0)
teria feito. (Ele também faz a mesma coisa que a condição de aparência ainda mais complicada while(+(+(+(+k--)))!=0)
teria feito. E esses parênteses não são realmente necessários; ele também faz a mesma coisa que while(+ + + +k--!=0)
teria feito.)
Mesmo descobrindo qual é a condição "normal"
while(k-- != 0)
faz é meio complicado. Há duas coisas acontecendo neste loop: Como o loop é executado potencialmente várias vezes, vamos:
- continuar fazendo
k--
, para tornar k
cada vez menor, mas também
- continue fazendo o corpo do loop, faça o que fizer.
Mas fazemos a k--
parte imediatamente, antes (ou no processo de) decidir se devemos fazer outra viagem pelo circuito. E lembre-se de que k--
"retorna" o valor antigo de k
, antes de diminuí-lo. Nesse programa, o valor inicial k
é 0. Portanto, k--
"retornará" o valor antigo 0 e atualize k
para -1. Mas o restante da condição é != 0
- mas, como acabamos de ver, na primeira vez que testamos a condição, obtivemos um 0. Portanto, não faremos nenhuma viagem pelo loop, portanto, não tentaremos executar o afirmação problemática k=k++
.
Em outras palavras, nesse loop específico, embora eu tenha dito que "existem duas coisas acontecendo", acontece que a coisa 1 acontece uma vez, mas a coisa 2 acontece zero vezes.
De qualquer forma, espero que agora esteja bem claro por que essa desculpa ruim para um programa acaba imprimindo -1 como o valor final de k
. Normalmente, não gosto de responder a perguntas do questionário como esta - parece trapaça -, mas neste caso, como discordo muito de todo o objetivo do exercício, não me importo.