Fórum Boolean nem true nem false #277685

18/04/2005

0

Delphi 6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var a,b:Boolean; Baiti:Byte;
begin
  a     := true;
  Baiti := 2;
  Move(Baiti, b, 1);
  if a and b then
    ShowMessage(´b é true´)
  else
  if a and not b then
    ShowMessage(´b é false´)
  else
  if a then
    ShowMessage(´b é ?´);
end;
Alguém poderia explicar ?


Kapak

Kapak

Responder

Posts

18/04/2005

Beppe

Caso 1) O Delphi trata 0 como False e 1 como True.
Caso 2) Em certas ocasiões, trata qualquer valor diferente de 0 como True.

Mas no caso dos operadores [b:df697bf3a3]and[/b:df697bf3a3], [b:df697bf3a3]or[/b:df697bf3a3] e [b:df697bf3a3]xor[/b:df697bf3a3], o procedimento é o mesmo dos inteiros. E sem olhar o código gerado, pode ser um tanto difícil adivinhar o que será feito.

O [b:df697bf3a3]not [/b:df697bf3a3]tem um tratamento especial em alguns casos. Dentro de um [b:df697bf3a3]if [/b:df697bf3a3]é o Caso 2. Numa atribuição, é o Caso 1.

Atribuição simples:
a and b = 01b and 10b = 0 = False
not b = 10b xor 01b = 11b = True

Teste if ou atribuição complexa:
a and b = 01b and 10b = 0 = False
a and not b = (01b <> 00b) and not (10b <> 00b) = 01b and not 01b = 01b and 00b = 00b = True

O problema é o Move. Use b := Baiti <> 0;

PS: o sufixo b é de binário


Responder

Gostei + 0

18/04/2005

Massuda

Internamente o tipo de dado Boolean é assumido como sendo uma enumeração do tipo
1
2
type
  Boolean = (False, True);

Quando você faz...
1
2
3
4
Baiti := 2;
Move(Baiti, b, 1);
// ou simplesmente
// b = Boolean(2)
...você está atribuindo um valor fora de faixa à variável b. A rigor, isso já é um erro.

Delphi avalia uma variável Boolean no estilo da linguagem C, ou seja, falso é ZERO e verdadeiro é NÃO-ZERO; assim
1
2
3
4
5
6
b := Boolean(2);
 
if b then
  {sempre executado}
else
  {nunca executado}

O problema são os operadores lógicos...

Os operadores lógicos AND, OR e XOR tratam os booleans como inteiros, de modo que o AND, OR e XOR são feitos bit-a-bit.
1
2
3
4
5
6
7
8
9
10
11
12
a := True;
b := Boolean(2);
 
if b then
  {sempre executado}
else
  {nunca executado}
 
if a and b then // = 1 and 2 = 0
  {nunca executado}
else
  {sempre executado}

O operador lógico NOT é implementado como sendo:
1
Not X = Boolean(Byte(X) Xor Ord(True))
de modo que
1
2
3
b := Boolean(8);
b := Not b;
// Byte(b) = 9


No caso, ao avaliar a expressão lógica nos if´s, cada parte da expressão é avaliada conforme o operador lógico utilizado e no final verifica se o resultado é ou não zero.

Lembro que no Pascal original, True = 0 e False = -1 (ou o contrário, não lembro), mas isso foi alterado nas primeiras versões do Delphi (quando surgiu o C++ Builder, acho).


Responder

Gostei + 0

18/04/2005

Marco Salles

beep :
O problema é o Move.


Massuda :
você está atribuindo um valor fora de faixa à variável b. A rigor, isso já é um erro


Massuda :
Lembro que no Pascal original, True = 0 e False = -1 (ou o contrário, não lembro),



Responder

Gostei + 0

18/04/2005

Aroldo Zanela

Colegas,


Syntax{$B+} or {$B-} {$BOOLEVAL ON} or {$BOOLEVAL OFF} Default{$B-} {$BOOLEVAL OFF} ScopeLocal Remarks The $B directive switches between the two different models of code generation for the and and or Boolean operators. In the {$B+} state, the compiler generates code for complete Boolean expression evaluation. This means that every operand of a Boolean expression built from the and and or operators is guaranteed to be evaluated, even when the result of the entire expression is already known. In the {$B-} state, the compiler generates code for short-circuit Boolean expression evaluation, which means that evaluation stops as soon as the result of the entire expression becomes evident in left to right order of evaluation. For further details, see the section ´Boolean operators´ in the Object Pascal Language Guide.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{$B+}
 
procedure TForm1.Button1Click(Sender: TObject);
var a:Boolean;
    b:Boolean;
    Baiti:Byte;
begin
  a     := true;
  Baiti := 2;
  Move(Baiti, b, SizeOf(Baiti));
  if a and b then
    ShowMessage(´b é true´)
  else
  if a and not b then
    ShowMessage(´b é false´)
  else
    ShowMessage(´b é ´+IntToStr(Integer(b)));
end;



Responder

Gostei + 0

18/04/2005

Kapak

Olá pessoal, obrigado pelas respostas apresentadas. Peguei este erro num programa que estava sujando a variável boleana. Confesso que ainda não entendí.
Mas no caso dos operadores and, or e xor, o procedimento é o mesmo dos inteiros.
Os operadores lógicos AND, OR e XOR tratam os booleans como inteiros, de modo que o AND, OR e XOR são feitos bit-a-bit.Código: a := True; b := Boolean(2); if b then {sempre executado} else {nunca executado} if a and b then // = 1 and 2 = 0
Mas se for feito:
1
2
3
{$B-}
if a and (b) then
  ShowMessage(´b é true´) // e é aqui que ele vem



Responder

Gostei + 0

18/04/2005

Kapak

Acho que ele deve tratar (b) como Boolean(b)


Responder

Gostei + 0

18/04/2005

Massuda

O que o Beppe e eu tentamos dizer é que quando uma expressão lógica envolve AND, OR e XOR, os booleans são tratados como inteiros. Isso significa que a expressão
1
if a and b then...
é na verdade vista pelo compilador como sendo
1
if Boolean(Integer(a) and Integer(b)) then...

Com relação a outra questão...
Mas se for feito:
1
2
3
{$B-}
if a and (b) then
  ShowMessage(´b é true´) // e é aqui que ele vem
O $B- faz com que o compilador tente simplificar as expressões lógicas.

No seu exemplo, a é sempre True, logo o compilador precisa apenas checar o valor de b, para saber se o AND é verdadeiro; como ele não precisa fazer o AND, ele apenas testa se B é não-zero, o que resulta em True.

Note que se o teste usasse OR ao invés de AND, o compilador nem precisava testar o valor de b, pois a já é True.


Responder

Gostei + 0

18/04/2005

Kapak

Ainda não entendí.
O $B- faz com que o compilador tente simplificar as expressões lógicas. No seu exemplo, a é sempre True, logo o compilador precisa apenas checar o valor de b, para saber se o AND é verdadeiro; como ele não precisa fazer o AND, ele apenas testa se B é não-zero, o que resulta em True.
1
2
3
$B-}
if a and b then    // Resulta em false
if a and (b) then // Resulta em true
No que os parênteses influenciam ?


Responder

Gostei + 0

18/04/2005

Massuda

1
2
if a and b then    // Resulta em false
if a and (b) then // Resulta em true
No que os parênteses influenciam ?
Os parênteses fazem o compilador avaliar a expressão numa ordem diferente... isso faz o compilador gerar código diferente em cada caso.

No primeiro caso, o compilador faz o AND entre a e b e acabou.
1
if (Integer(a) and Integer(b)) <> 0 then...


No segundo caso, o compilador avalia cada lado do AND separadamente, gerando um código mais ou menos assim
1
2
if Integer(a) <> 0 then
  if Integer(b) <> 0 then...


Sinceramente, num primeiro momento eu acharia que é um bug do compilador, mas como a causa disso é um valor fora de faixa, eu acho aceitável que quem fez o compilador diga que isso é um comportamento indefinido.


Responder

Gostei + 0

18/04/2005

Kapak

Já acho que [b:67b9d8fc1a](b)[/b:67b9d8fc1a] num [b:67b9d8fc1a]and[/b:67b9d8fc1a] é tratado como Integer(Boolean(b)) e não Integer(b).


Responder

Gostei + 0

18/04/2005

Massuda

Já acho que [b:bb15f13d08](b)[/b:bb15f13d08] num [b:bb15f13d08]and[/b:bb15f13d08] é tratado como Integer(Boolean(b)) e não Integer(b).
Eu dei uma olhada no código gerado... o que o compilador gera é mais ou menos o que coloquei no meu post anterior.


Responder

Gostei + 0

18/04/2005

Kapak

1
2
if Integer(a) <> 0 then
  if Integer(b) <> 0 then...
Mas aí ele faz um if encadeado, ou seja, insere uma instrução adicional e, consequentemente perde mais tempo.


Responder

Gostei + 0

18/04/2005

Anderson_blumenau

Entao beppe isso significa q o compilador usa uma tabela logica pra achar os valores?

tipo

0 eh falso
1 eh verdadeiro


1
2
3
4
5
6
7
A and B
 
0  0 =  0 falso
1  0 =  0 falso
1  1 =  1 verdadeiro
 
Definicao: A saida eh verdade se somente todas as entradas forem verdade



Responder

Gostei + 0

18/04/2005

Beppe

Entao beppe isso significa q o compilador usa uma tabela logica pra achar os valores?

Isso em condições normais. No caso do [b:bedb633d4e]kapak[/b:bedb633d4e], o código que ele usa depende de como o compilador interpreta em cada caso. Reitero que iso não deve ser usado(Move´s e typecast´s), já que torna o código menos legível e difícil de manter.


Responder

Gostei + 0

18/04/2005

Kapak

Reitero que iso não deve ser usado(Move´s e typecast´s), já que torna o código menos legível e difícil de manter.
Num caso por ex de vc montar um buffer de dados p/ serem enviados via Sockets. Eu utilizo ReallocMem e Move p/ depois dar um SendBuf c/ este ponteiro.
Como vc faria ?


Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar