我必须拿起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的某个地方陈述过这种行为吗?
答案 0 :(得分:20)
布尔短路评估
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中对False
和True
进行测试。总是写这样的代码:
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
答案 2 :(得分:0)
为避免不调用函数,您可以这样做:
bool_somefunc := (somefunc() = 42);
bool_anotherfunc := (anotherfunc() = 17);
if ( (bool_somefunc = False) and (bool_anotherfunc = True) ) then
这确保了每个功能都被称为短期 打开或关闭。