德尔福'AND'评估有2个条件

时间:2013-02-26 08:15:55

标签: delphi

我必须拿起Delphi来完成我正在做的最近合同工作,我想让某人澄清的一件事是在条件语句中执行逻辑,例如if

我来自C / C ++和这些语言的背景,只要知道if语句失败,其余逻辑就不会执行。例如:

if (somefunc() == FALSE && anotherfunc() == TRUE)

在上述情况下,如果somefunc()返回TRUE,则永远不会调用anotherfunc()

从目前为止我所看到的Delphi中,这并不成立。相反,

if (somefunc() = False and anotherfunc() = True) then

然后,无论somefunc()返回什么,都会调用anotherfunc()

我已经阅读了各种Delphi书籍,并重读了一些有条件的章节,并且在任何地方都找不到这种行为。任何人都能指出我在Delphi或Pascal的某个地方陈述过这种行为吗?

3 个答案:

答案 0 :(得分:20)

documentation link is here

  

布尔短路评估

 
Type    Switch 
Syntax  {$B+} or {$B-} {$BOOLEVAL ON} or {$BOOLEVAL OFF} 
Default {$B-} {$BOOLEVAL OFF} 
Scope   Local 
     

$ B指令在两个不同的Delphi模型之间切换   以及布尔运算符的代码生成。

     

在{$ B +}状态下,编译器生成完整布尔值的代码   表达评价。这意味着布尔值的每个操作数   保证使用和和或运算符构建的表达式   即使整个表达式的结果已经存在,也会进行评估   已知的。

     

在{$ B-}状态下,编译器生成短路代码   布尔表达式求值,表示求值停止为   很快,整个表达的结果在左边变得明显   正确的评估顺序。

如您所见,默认选项用于短路评估。


不幸的是,你的测试中有点混淆了。事实上,您的Delphi代码与C代码完全不同。

if (somefunc() == FALSE && anotherfunc() == TRUE)      // C code
if (somefunc() = False and anotherfunc() = True) then   // Delphi code

在Delphi中,and运算符的higher precedence比等于运算符=高。这意味着您的Delphi代码等同于:

if (somefunc() = (True and anotherfunc()) = True) then

但在C和C ++中,优先级是另一种方式。因此&&lower precedence而不是==。因此,无论短路评估如何,您问题中的Delphi和C ++ if语句在逻辑上都是不同的。

我很确定你真的打算写这样的Delphi代码:

if ((somefunc() = False) and (anotherfunc() = True)) then 

这将提供与C ++代码相同的逻辑,并且由于短路评估,您会看到相同的行为。

最后,你永远不应该在Delphi中对FalseTrue进行测试。总是写这样的代码:

if not somefunc() and anotherfunc() then 

答案 1 :(得分:4)

如果您的函数anotherfunc()在此代码中被调用

if (somefunc() = False and anotherfunc() = True) then

然后你设置了BOOLEVAL ON

正如David指出编译器首先评估False and anotherfunc()

BOOLEVAL OFF模式下,编译器知道,False and AnyBoolState将导致False因此anotherfunc()未被调用(实际上它永远不会被调用)。

作为一个简单的测试,我扩展了jachaguate程序以显示你的表达式

program AndEvaluation;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils;

function FalseFunc( const AName : string ) : Boolean;
begin
  Write( AName, '(False)', '-' );
  Result := False;
end;

function TrueFunc( const AName : string ) : Boolean;
begin
  Write( AName, '(True)', '-' );
  Result := True;
end;

begin
  try

    // (somefunc() = False and anotherfunc() = True)
    //
    // in this testcase translated to:
    //
    // somefunc()    => FalseFunc( 'First' )
    // False         => FalseFunc( 'Second' )
    // anotherfunc() => TrueFunc( 'Third' )
    // True          => TrueFunc( 'Fourth' )

{$B+}
    Writeln( 'BOOLEVAL ON' );
    if ( FalseFunc( 'First' ) = FalseFunc( 'Second' ) and TrueFunc( 'Third' ) = TrueFunc( 'Fourth' ) )
    then
      Writeln( 'True' )
    else
      Writeln( 'False' );
{$B-}
    Writeln( 'BOOLEVAL OFF' );
    if ( FalseFunc( 'First' ) = FalseFunc( 'Second' ) and TrueFunc( 'Third' ) = TrueFunc( 'Fourth' ) )
    then
      Writeln( 'True' )
    else
      Writeln( 'False' );

  except
    on E : Exception do
      Writeln( E.ClassName, ': ', E.Message );
  end;

  ReadLn;

end.

现在让我们来看看结果

BOOLEVAL ON
Second(False)-Third(True)-First(False)-Fourth(True)-True

BOOLEVAL OFF
First(False)-Second(False)-Fourth(True)-True

正如输出说明BOOLEVAL ON anotherfunc()在调用 somefunc()之前将BOOLEVAL OFF称为

anotherfunc() if (somefunc() == FALSE && anotherfunc() == FALSE) 从不被调用。

如果你想和

一样
if ( somefunc() = False ) and ( anotherfunc() = False ) then

你必须像这样翻译它

if not somefunc() and not anotherfunc() then

更好更短的方式

if not( somefunc() or anotherfunc() ) then

或者甚至更短

anotherfunc()

但是,每次必须设置BOOLEVAL OFF

时,要避免调用{{1}}

答案 2 :(得分:0)

为避免不调用函数,您可以这样做:

  bool_somefunc := (somefunc() = 42);
  bool_anotherfunc := (anotherfunc() = 17);
  if ( (bool_somefunc = False) and (bool_anotherfunc = True) ) then

这确保了每个功能都被称为短期 打开或关闭。