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

nrj*_*one 15 delphi

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

我来自C/C++和这些语言的背景,一旦if声明失败,其余的逻辑就不会被执行.例如:

if (somefunc() == FALSE && anotherfunc() == TRUE)
Run Code Online (Sandbox Code Playgroud)

在上述情况下,如果somefunc()回报率TRUEanotherfunc()不会被调用.

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

if (somefunc() = False and anotherfunc() = True) then
Run Code Online (Sandbox Code Playgroud)

那么,无论什么somefunc()回报,anotherfunc()都会被召唤.

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

Dav*_*nan 21

文档的链接在这里:

布尔短路评估

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

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

在{$ B +}状态下,编译器生成用于完整布尔表达式求值的代码.这意味着,即使已知整个表达式的结果,也可以保证评估从and和or运算符构建的布尔表达式的每个操作数.

在{$ B-}状态下,编译器生成用于短路布尔表达式求值的代码,这意味着一旦整个表达式的结果从左到右的评估顺序变得明显,评估就会停止.

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


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

if (somefunc() == FALSE && anotherfunc() == TRUE)      // C code
if (somefunc() = False and anotherfunc() = True) then   // Delphi code
Run Code Online (Sandbox Code Playgroud)

在Delphi中,and运算符的优先级高于相等运算符=.这意味着您的Delphi代码相当于:

if (somefunc() = (True and anotherfunc()) = True) then
Run Code Online (Sandbox Code Playgroud)

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

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

if ((somefunc() = False) and (anotherfunc() = True)) then 
Run Code Online (Sandbox Code Playgroud)

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

最后,你永远不应该对测试FalseTrue德尔福.总是写这样的代码:

if not somefunc() and anotherfunc() then 
Run Code Online (Sandbox Code Playgroud)

  • @J...是的,我也一直在为此而挣扎。我总是在我的 C# 代码中得到额外的括号,因为我永远记不起运算符的优先级。 (2认同)
  • @nrjohnstone 好吧,`if` 需要一个计算结果为 `Boolean` 的表达式。如果你有一个返回 `Boolean` 的函数,那么它已经是一个计算结果为 `Boolean` 的表达式。测试“真”或“假”显然是多余的。正如您所发现的那样,这样做会将您带入括号地狱。您可能来自不包含真正布尔类型的旧版本 C 的背景。德尔福不一样。 (2认同)

Sir*_*ufo 5

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

if (somefunc() = False and anotherfunc() = True) then
Run Code Online (Sandbox Code Playgroud)

那么你已经设置了 BOOLEVAL ON

正如大卫指出的,编译器首先评估 False and anotherfunc()

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

作为一个简单的测试,我扩展了 jachagate 程序来显示你的表情

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.
Run Code Online (Sandbox Code Playgroud)

现在让我们看看结果

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

BOOLEVAL OFF
First(False)-Second(False)-Fourth(True)-True
Run Code Online (Sandbox Code Playgroud)

正如输出解释了在调用之前调用BOOLEVAL ON您的anotherfunc()遗嘱。 somefunc()

随着BOOLEVAL OFFanotherfunc()永远不会被调用。

如果你想拥有相同的

if (somefunc() == FALSE && anotherfunc() == FALSE)
Run Code Online (Sandbox Code Playgroud)

你必须像这样翻译它

if ( somefunc() = False ) and ( anotherfunc() = False ) then
Run Code Online (Sandbox Code Playgroud)

或者更好更短的方式

if not somefunc() and not anotherfunc() then
Run Code Online (Sandbox Code Playgroud)

或者甚至更短

if not( somefunc() or anotherfunc() ) then
Run Code Online (Sandbox Code Playgroud)

但是为了避免anotherfunc()每次必须设置时都被调用BOOLEVAL OFF