delphi - Delphi中的 boolean 表达式求值顺序?

标签 delphi boolean pascal logical-operators

if exp1 and exp2 and exp3 then
    //something
在 Delphi 中,exp1、exp2 和 exp3(当然它们都是 Boolean)的求值顺序是定义的还是随机的?

最佳答案

评估顺序仅在 Boolean Short-Circuit Evaluation 时定义已启用。然后,作为 Complete Versus Short-Circuit Boolean Evaluation 中的文档解释说,评估是从左到右的。
如果未启用 boolean 短路评估,则顺序未定义。以下代码演示了这一点:

{$APPTYPE CONSOLE}
    
function A: boolean;
begin
  Result := True;
  Write('A ');
end;
    
function B: string;
begin
  Result := '';
  Write('B ');
end;
    
function C: Integer;
begin
  Result := 0;
  Write('C ');
end;
    
begin
  {$O+}
  Writeln('short circuit on');
  {$B-}
  if A and (B = '') and (C = 0) then Writeln;
  Writeln('short circuit off');
  {$B+}
  if A and (B = '') and (C = 0) then Writeln;
end.
对于第一个,您会打印 A B C ,第二个你会得到 B A C .
它是为 Win32 编译的——为了让它变得有趣,并把这个未定义的点带回家,让我们在 Win64 上运行它,我们得到 A B C在这两种情况下。
你可能会说:“好吧,但也许只是 B 被先调用了,但 boolean 表达式 B = '' 的计算是以正确的顺序计算的。”让我们看一下执行的汇编代码:
if A and (B = '') and (C = 0) then Writeln;
0040B17C 8D45E8           lea eax,[ebp-$18]
0040B17F E864EAFFFF       call B
0040B184 837DE800         cmp dword ptr [ebp-$18],$00
0040B188 0F94C3           setz bl
0040B18B E81CEAFFFF       call A
0040B190 22D8             and bl,al
0040B192 E891EAFFFF       call C
0040B197 85C0             test eax,eax
0040B199 0F94C0           setz al
0040B19C 22D8             and bl,al
不:
  • 调用 B , 比较 ''
  • 调用 A , and它与字符串比较的结果
  • 调用 C , 比较 0 , and它与上一个 and 的结果

  • 翻译成(按从左到右的顺序写):
    ((B = '') and A) and (C = 0)
    
    附录:因为我在另一个答案中看到了这一点,并在评论中进行了讨论。括号不是强制操作数计算顺序的解决方案。您只能对操作进行分组,但编译器可能仍会决定首先评估正确的操作数。
    在上面的代码中,没有任何括号可以得到 A B C仅仅是因为编译器翻转了前两个操作数。然而,它然后从左到右执行运算符,这很容易混淆 - 问题不在于是第一个还是第二个 and首先执行的是 boolean 表达式的顺序 - 操作数。

    关于delphi - Delphi中的 boolean 表达式求值顺序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66715195/

    相关文章:

    delphi - 如何使用 Free Pascal 调用物理连接的硬盘列表,或者如果失败,则使用 Delphi?

    Delphi Tokyo 10.2 的 Powershell 静默/无人值守安装 - 用于在 win docker 容器中使用 CI

    javascript - 如何停止setInterval?清除间隔不起作用

    c++ - bool 从结构导致 "error: expression must have class type"

    treeview - Inno Setup 中的 TTreeView

    pascal - 定义未知数量的变量

    delphi - 如何自动滚动到 RichEdit 的末尾?

    delphi - CEF(Chromium 嵌入式框架)与 DEP(数据执行保护)

    Java减少对象的大小

    delphi - ffmpeg 和 windows 命令行