Delphi中if语句的求值顺序

Delphi中if语句的求值顺序,delphi,Delphi,我知道以下函数语句的答案: if (TestFunc1()) and (TestFunc2()) then DoSomething(); 这个问题很好地回答了这个问题: 例如,您可以通过调试或记录来轻松地测试这一点。但是,在本例中,您将如何测试编译器正在执行的操作(假设ech参数定义为布尔值): 是的,我知道参数最好隐藏在访问器函数后面……但是有没有一种聪明的方法来测试是否访问了SomeObj2?答案与您链接到的问题相同。作为和的操作数的表达式是函数调用还是变量并不重要。在以下情况下

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

if (TestFunc1()) and (TestFunc2()) then
    DoSomething();
这个问题很好地回答了这个问题:

例如,您可以通过调试或记录来轻松地测试这一点。但是,在本例中,您将如何测试编译器正在执行的操作(假设ech参数定义为布尔值):


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

答案与您链接到的问题相同。作为
的操作数的表达式是函数调用还是变量并不重要。在以下情况下,将计算第二个操作数:

  • 短路评估未启用,或
  • 短路计算已启用,第一个操作数的计算结果为真
  • 默认的编译器选项启用了短路评估,我不知道在什么情况下更改它是有意义的。因此,假设您在启用短路计算的情况下编译,则当且仅当第一个操作数的计算结果为true时,才会计算第二个操作数

    如果您希望在调试器下看到这一点,请尝试此程序并进行短路评估或不进行短路评估:

    {$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
    的计算是一个运行时错误。对于短路评估,没有运行时错误


    事实上,这一具体示例是应启用短路评估的最佳原因之一。否则,这样的代码将过于冗长

    设置
    SomeObj1.bNaughtyGlobal1:=False
    SomeObj2:=nil
    。如果编译器行为不正常,并且对
    表达式的两侧都进行了计算,那么当程序试图从空引用中读取
    bNaughtyGlobal2
    值时,就会出现访问冲突。

    if (SomeObj1.bNaughtyGlobal1) and (SomeObj2.bNaughtyGlobal2) then
    
    现在将程序运行到断点。 打开CPU窗口(查看->调试窗口->CPU)并逐步完成处理器指令。
    在这里,您将看到跳转指令,并且您还将看到,如果SomeObj1.bNaughtyGlobal1为false,则不会计算任何其他对象,而不是您的SomeObj2对象。

    是的,我启用了短路编译选项(项目>选项>编译器>完全布尔值=OFF)。我知道编译应该是相同的,但是使用函数可以很容易地测试编译器所做的工作。想知道是否有一种聪明的方法可以用参数来证明这一点。是的,谢谢你的例子。尝试了这两个编译器选项,但它按预期工作或失败。我做了一个小的修改,使示例更加清晰(希望你也这么认为)。短路编译器选项是绝对值得推荐的…现在我对它有了更好的理解!该示例需要一些小的调整才能在Delphi7中编译。在记录“end”后需要分号。不支持变量初始化(n:Integer=5;)。再次感谢。谢谢你的分号更正。变量初始化很好。根据我的代码,它必须是全局的。问题中的代码是一个完整的程序。所以P是一个全局变量。将它粘贴到一个.dpr文件中,一切正常。啊,是的,P是全局的。我将它作为一个局部变量测试到一个函数。再次感谢。您所说的“测试是否正在访问SomeObj2”是什么意思?当你读到SomeObj2.bNaughtyGlobal2时,它会取SomeObj2应该位于的地址,加上bNaughtyGlobal2应该位于的偏移量,然后在该地址得到该值。是的,这正是我的意思。在回答这个问题几分钟后,您自己的回答是一个不错的答案,谢谢。是什么让您认为对象的属性是全局的?@Craig:“全局”的意思是,该属性在对象的类定义中被定义为公共的。虽然不是严格意义上的相关,因为变量可能是局部变量。很好,实际上在发布问题30分钟后想到了这一点。只是尝试了一下,它就工作了!不太熟悉汇编程序,但我能够看到两个“cmp”语句,第二个被跳过。谢谢你的提示@另一件有趣的事是,如果你关闭短路评估,你会看到不同的机器代码。是的,很好地发现了。我可以看到,当短路被关闭时,两个“cmp”语句将在一个“jmp”被命中之前运行。
    if (SomeObj1.bNaughtyGlobal1) and (SomeObj2.bNaughtyGlobal2) then