Então podemos fazer uma operação lógica e atribuir a uma variável inteira. Veja o exemplo abaixo:
static int valido( a,b,c )
int a,b,c ;
{
return ( a < b ) && ( b < c ) ;
}
int main()
{
int x,y,z,l,m,n,b ;
/* ... */
if( valido( x,y,z ) )
{
/* ... */
}
if( b = valido( l,m,n ) )
{
/* ... */
}
if( b && ( l > z ) )
{
/* ... */
}
}
No exemplo acima uma função retorna o resultado de uma expressão lógica, e no segundo if o valor retornado pela função também é atribuído à variável b, que é usada na expressão do terceiro if.
Mas que valores inteiros a função valido() pode retornar? Vamos testar:
#include <stdio.h>
static int valido( a,b,c )
int a,b,c ;
{
return ( a < b ) && ( b < c ) ;
}
int main()
{
printf( "%d\n",valido( 1,2,3 ) );
printf( "%d\n",valido( 3,2,1 ) );
}
E o resultado é (e que rufem os tambores)...
1
0
Quando verdadeira, a expressão retorna 1, quando falsa, retorna 0.
Na realidade, o compilador só gera código que resulte num inteiro quando é pedido, pois isto é custoso, e para determinar se um resultado é verdadeiro ou não, uma instrução de comparação é executada pelo processador, mudando, conforme o resultado desta comparação, o estado de um conjunto de flags. Intruções de jumps condicionais, que dependem destas flags, são usadas para fazer os desvios na execução do código. (De novo, para um melhor entendimento, é necessário saber Assembler.) Todos os compiladores fazem isto, em todas as linguagens, não somente os compiladores C.
Não importando como o compilador vai gerar o código, ao nível do programador a expressão age da mesma forma, como uma expressão do tipo inteiro. E isto serve para criar uns atalhos.
Se resultado de uma expressão lógica é 0 ou 1, mas ela é uma operação inteira, onde outros números são aceitos, o que acontece com os valores diferente de 0 e 1? A solução mais simples é só definir o falso como 0, que é bem fácil de testar (O PDP 11/70 tinha uma instrução para testar sem fazer comparação, mudando as flags de acordo com o valor testado, e outros processadores podem fazer operações de bits, como or ou and, que alteram as flags de acordo.), e o resto como sendo verdadeiro. Isto tem implicações úteis.
int i ;
/* if( i != 0 ) */
if( i )
{
/* ... */
}
/* if( i == 0 ) */
if( ! i )
{
/* ... */
}
for( i = 10 ; i ; i-- )
{
/* ... */
}
Testes podem ser simplificados. (O truque do for acima merece uma explicação melhor, pois é uma otimização de código, porém é assunto para um outro artigo. Mas você já pode começar a deduzir.)
Uma otimização de uso de memória pode ser feita usando a Dualidade char/int. Quando necessitar de um array para guardar resultados de variáveis lógicas, pode usar o tipo char, fazendo um array de char, e gastando menos memória.
Muitos programadores C criam o boolean, só por questões de legibilidade e elegância, usando uma das diversas formas abaixo, ou alguma outra não mostrada.
#define boolean int
#define boolean char
E criam true e false usando uma das diversas formas existentes, mas gosto da forma abaixo:
#define FALSE (0)
#define TRUE (! FALSE )
De novo, existem muitas formas de fazer isto.
Nenhum comentário:
Postar um comentário