Delphi中if语句的评估顺序

时间:2015-03-13 13:24:54

标签: delphi

我知道以下函数语句的答案:

if (TestFunc1()) and (TestFunc2()) then
    DoSomething();

这个问题很好地解答了: Delphi 'AND' evaluation with 2 conditions

比如说,你可以通过调试或记录来轻松测试。但是你如何测试编译器在这个例子中做了什么(比如说ech参数定义为布尔值):

if (SomeObj1.bNaughtyGlobal1) and (SomeObj2.bNaughtyGlobal2) then
    DoSomething();

是的,我知道参数最好隐藏在访问器函数后面......但是有没有一种聪明的方法来测试是否正在访问SomeObj2?

3 个答案:

答案 0 :(得分:4)

答案与您链接的问题相同。作为and的操作数的表达式是函数调用还是变量,这并不重要。如果符合以下条件,将评估第二个操作数:

  1. 未启用短路评估,或
  2. 启用短路评估,第一个操作数评估为真。
  3. 默认编译器选项启用了短路评估,并且我不知道任何改变它的情况。因此,假设您在启用短路评估的情况下进行编译,那么当且仅当第一个操作数的计算结果为真时,才会计算第二个操作数。

    如果您希望在调试器下看到这个,请尝试使用和不使用短路评估的程序:

    {$APPTYPE CONSOLE}
    
    type 
      TMyRecord = record
        foo: Integer;
      end;
      PMyRecord = ^TMyRecord;
    
    var 
      P: PMyRecord = nil;
    begin
      if Assigned(P) and (P.foo=1) then 
        Writeln;
    end.
    

    没有短路,P.foo的评估是运行时错误。通过短路评估,没有运行时错误。

    确实,这个具体的例子是应该启用短路评估的最佳原因之一。否则这样的代码会过于冗长。

答案 1 :(得分:3)

上设置断点
if (SomeObj1.bNaughtyGlobal1) and (SomeObj2.bNaughtyGlobal2) then

现在将程序运行到断点。 打开CPU窗口(view-> Debug Windows-> CPU)并逐步执行处理器指令。 在那里你会看到跳转指令,你也会看到,如果SomeObj1.bNaughtyGlobal1为false,则不会评估任何其他内容,而不是你的SomeObj2对象。

答案 2 :(得分:1)

设置SomeObj1.bNaughtyGlobal1 := FalseSomeObj2 := nil。如果编译器行为不端并评估and表达式的两边,那么当程序尝试从空引用读取bNaughtyGlobal2值时,您将获得访问冲突。