Boolean nem true nem false
Delphi 6Alguém poderia explicar ?
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;

Kapak
Curtidas 0
Respostas

Beppe
18/04/2005
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
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
GOSTEI 0

Massuda
18/04/2005
Internamente o tipo de dado Boolean é assumido como sendo uma enumeração do tipo
Quando você faz......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
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.
O operador lógico NOT é implementado como sendo:de modo que
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).
type Boolean = (False, True);
Quando você faz...
Baiti := 2; Move(Baiti, b, 1); // ou simplesmente // b = Boolean(2)
Delphi avalia uma variável Boolean no estilo da linguagem C, ou seja, falso é ZERO e verdadeiro é NÃO-ZERO; assim
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.
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:
Not X = Boolean(Byte(X) Xor Ord(True))
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).
GOSTEI 0

Marco Salles
18/04/2005
beep :
Massuda :
Massuda :
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),
GOSTEI 0

Aroldo Zanela
18/04/2005
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.
{$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;
GOSTEI 0

Kapak
18/04/2005
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:{$B-} if a and (b) then ShowMessage(´b é true´) // e é aqui que ele vem
GOSTEI 0

Kapak
18/04/2005
Acho que ele deve tratar (b) como Boolean(b)
GOSTEI 0

Massuda
18/04/2005
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é na verdade vista pelo compilador como sendo
Com relação a outra questão...
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.
if a and b then...
if Boolean(Integer(a) and Integer(b)) then...
Com relação a outra questão...
Mas se for feito:
O $B- faz com que o compilador tente simplificar as expressões lógicas.{$B-} if a and (b) then ShowMessage(´b é true´) // e é aqui que ele vem
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.
GOSTEI 0

Kapak
18/04/2005
Ainda não entendí.No que os parênteses influenciam ?
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.
$B-} if a and b then // Resulta em false if a and (b) then // Resulta em true
GOSTEI 0

Massuda
18/04/2005
if a and b then // Resulta em false if a and (b) then // Resulta em true
No primeiro caso, o compilador faz o AND entre a e b e acabou.
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
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.
GOSTEI 0

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

Massuda
18/04/2005
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.GOSTEI 0

Kapak
18/04/2005
if Integer(a) <> 0 then if Integer(b) <> 0 then...
GOSTEI 0

Anderson_blumenau
18/04/2005
Entao beppe isso significa q o compilador usa uma tabela logica pra achar os valores?
tipo
0 eh falso
1 eh verdadeiro
tipo
0 eh falso
1 eh verdadeiro
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
GOSTEI 0

Beppe
18/04/2005
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.
GOSTEI 0

Kapak
18/04/2005
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 ?
GOSTEI 0

Beppe
18/04/2005
Prefira registros:
Isto resolve o problema na maior parte dos casos. Em outros casos, pode usar ponteiro para um record, neste caso dá pra abrigar um array de tamanho ´flexível´.
type TRec = record B: Boolean; I: Integer; D: Double; S: ShortString; // = String[255] end; var R: TRec; begin R.B := True; ... Socket.SendBuf(@R, SizeOf(TRec)); end;
Isto resolve o problema na maior parte dos casos. Em outros casos, pode usar ponteiro para um record, neste caso dá pra abrigar um array de tamanho ´flexível´.
GOSTEI 0

Kapak
18/04/2005
Olá Beppe, conheço bem registros e os utilizo com bastante frequência.
No meu caso, leio um cursor de dados de um Dataset e tenho que enviá-los via Sockets p/ a aplicação cliente; pode vir qualquer tipo de dado inclusive blobs; é por isso que utilizo ReallocMem e Move(que na verdade não é um move e sim um copy). Se vc já ouviu falar num objeto chamado RPCBuffer, pode ver que ele utiliza a mesma lógica p/ alocação de memória e, eu como tive que escrever uma classe semelhante pq esta não implementa Sockets e nem consegue atualizar os dados já inseridos, faço alocação de memória e manipulação de dados com estes comandos.
É obvio que quando vc pode facilitar leitura de código, vc não vai complicar; mas tem casos que não dá.
No meu caso, leio um cursor de dados de um Dataset e tenho que enviá-los via Sockets p/ a aplicação cliente; pode vir qualquer tipo de dado inclusive blobs; é por isso que utilizo ReallocMem e Move(que na verdade não é um move e sim um copy). Se vc já ouviu falar num objeto chamado RPCBuffer, pode ver que ele utiliza a mesma lógica p/ alocação de memória e, eu como tive que escrever uma classe semelhante pq esta não implementa Sockets e nem consegue atualizar os dados já inseridos, faço alocação de memória e manipulação de dados com estes comandos.
É obvio que quando vc pode facilitar leitura de código, vc não vai complicar; mas tem casos que não dá.
GOSTEI 0

Beppe
18/04/2005
Então acho que vc se encaixa na segunda situação. Pode usar ReallocMem, mas creio que ainda pode evitar os Move´s, a não ser que são inúmeras os registros que vc teria que criar.
É isso que vc pretende?
var P: Pointer; begin // aloque memória para P with TRec(P^) do begin B := True; S := ´Olá´; end; Socket.SendBuf(P, SizeOf(TRec)); end;
É isso que vc pretende?
GOSTEI 0

Kapak
18/04/2005
Esse objeto já está criado e funcionando; ele cria uma tabela bidimensional(registros/campos) em memória e vc navega como num Dataset. Trabalha c/ ReallocMem e Moves pq não são só tipos de dados simples, mas também arrays simples, arrays de type records, lógica de Treeviews e blobs.
GOSTEI 0