34
Fluxo de Controle
Se x é negativo, então (x >= 0) é false. Como você pode ver nas tabelas do Painel 2.1, quando uma subexpressão em uma expressão && é false, toda a expressão é false, não importa se a outra expressão é true ou false. Assim, se sabemos que a primeira expressão é false, não há necessidade de avaliar a segunda expressão. Algo similar acontece com expressões com ||. Se a primeira de duas expressões unidas pelo operador || é true, então se sabe que toda a expressão é true, sem importar se a segunda expressão é true ou false. A linguagem C++ utiliza esse fato para, às vezes, poupar a si própria o trabalho de avaliar a segunda subexpressão em uma expressão lógica ligada por um && ou ||. O C++ avalia primeiro a expressão mais à esquerda das duas expressões unidas por && ou ||. Se esta fornece informação suficiente para determinar o valor final da expressão (independentemente do valor da segunda expressão), o C++ não se preocupa em avaliar a segunda expressão. Esse método de avaliação é chamado avaliação curto-circuito. Algumas outras linguagens, que não C++, utilizam a avaliação completa . Na avaliação completa, quando duas expressões estão unidas por && ou ||, ambas as subexpressões são sempre avaliadas e depois se utilizam as tabelas de verdade para obter o valor da expressão final. Tanto a avaliação curto-circuito quanto a avaliação completa fornecem a mesma resposta, então por que você deveria se preocupar se o C++ utiliza a avaliação curto-circuito? Na maioria das vezes, não precisa se preocupar. Desde que ambas as subexpressões unidas por && ou || possuam um valor, os dois métodos produzem o mesmo resultado. Entretanto, se a segunda subexpressão é indefinida, talvez você fique feliz em saber que C++ utiliza a avaliação curto-circuito. Vamos ver um exemplo que ilustra esta questão. Considere as seguintes linhas: if (
(criancas != 0) && (( pedacos/criancas) >= 2) ) cout << "Cada criança pode ficar com dois pedacos!";
Se o valor de criancas não é zero, esse comando não envolve problemas. Entretanto, suponha que o valor de criancas seja zero; considere como a avaliação curto-circuito lida com esse caso. A expressão (criancas != 0) dá como resultado false, então não haveria necessidade de avaliar a segunda expressão. Utilizando a avaliação curto-circuito, C++ diz que toda a expressão é false, sem se preocupar em avaliar a segunda expressão. Isso impede um erro de execução, já que a avaliação da segunda expressão envolveria uma divisão por zero. VALORES INTEIROS PODEM SER USADOS COMO VALORES BOOLEANOS
O C++ às vezes utiliza inteiros como se fossem valores booleanos e valores bool como se fossem inteiros. Em particular, o C++ converte o inteiro 1 em true e o inteiro 0 em false, e vice-versa. A situação é ainda mais complicada do que simplesmente utilizar 1 para true e 0 para false. O compilador tratará qualquer número não-zero como se fosse o valor true e 0 como se fosse o valor false. Desde que você não cometa erros ao escrever expressões booleanas, essa conversão não causa problemas. Entretanto, quando você está fazendo uma depuração (debug ), pode ser útil saber que o compilador aceita combinar inteiros utilizando operadores booleanos &&, || e !. Por exemplo, suponha que você queira uma expressão booleana que seja true desde que o tempo não tenha ainda se esgotado (em algum jogo ou processo). Você poderia utilizar: !tempo > limite
Isso parece perfeito se você ler em voz alta: "não-tempo maior que limite". A expressão booleana está errada, todavia, e o compilador não emitirá uma mensagem de erro. O compilador aplicará as regras de precedência do Painel 2.3 e interpretará sua expressão booleana como o seguinte: (!tempo) > limite
Isso parece absurdo, e intuitivamente é absurdo. Se o valor do tempo é, por exemplo, 36, qual poderia ser o significado de (!tempo)? Afinal, isso é o equivalente a "não 36". Mas em C++ qualquer inteiro não-zero se converte em true e 0 é convertido em false. Assim, !36 é interpretado como "não true" e produz como resultado false, que é convertido novamente em 0, porque estamos fazendo a comparação com um int. O que queremos como valor dessa expressão booleana e o que o C++ nos fornece não é o mesmo. Se tempo possui um valor de 36 e limite, um valor de 60, você quer que a expressão booleana acima produza como resultado true (porque é não true que tempo > limite). Infelizmente, a expressão booleana, em vez disso, é executada da seguinte forma: (!tempo) é false e convertido em 0 e, assim, toda a expressão booleana é equivalente a: 0 > limite
O que, por sua vez, é equivalente a 0 > 60, porque 60 é o valor de limite e isso é avaliado como false. Assim, a expressão lógica acima é avaliada como false, quando você desejaria que fosse true. Há duas formas de corrigir esse problema. Uma forma é usar o operador ! corretamente. Quando usar o operador !, inclua parênteses em torno do argumento. A forma correta de se escrever a expressão booleana acima é