Delphi中if语句的评估顺序
Posted
技术标签:
【中文标题】Delphi中if语句的评估顺序【英文标题】:Evaluation order for if statement in Delphi 【发布时间】:2015-03-13 13:24:54 【问题描述】:我知道以下函数语句的答案:
if (TestFunc1()) and (TestFunc2()) then
DoSomething();
这个问题很好地回答了这个问题: Delphi 'AND' evaluation with 2 conditions
例如,您可以通过调试或记录来轻松测试这一点。但是在这个例子中,你将如何测试编译器正在做什么(比如 ech 参数被定义为布尔值):
if (SomeObj1.bNaughtyGlobal1) and (SomeObj2.bNaughtyGlobal2) then
DoSomething();
是的,我知道理想情况下参数会隐藏在访问器函数后面...但是有没有聪明的方法来测试 SomeObj2 是否正在被访问?
【问题讨论】:
“测试 SomeObj2 是否被访问”是什么意思?当您阅读 SomeObj2.bNaughtyGlobal2 时会发生什么,它将获取 SomeObj2 应该是的地址,添加 bNaughtyGlobal2 应该是的偏移量并在该地址获取该值。 是的,这正是我的意思。在这个问题之后几分钟你自己的答案是一个不错的答案,谢谢。 是什么让你认为对象的属性是全局的? @Craig: “全局”,因为该属性在对象的类定义中被定义为公共。但并不严格相关,因为变量可能是本地的。 【参考方案1】:答案与您链接到的问题相同。作为and
的操作数的表达式是函数调用还是变量并不重要。如果满足以下条件,将评估第二个操作数:
-
未启用短路评估,或
短路评估已启用,第一个操作数评估为真。
默认编译器选项启用了短路评估,我不知道在任何情况下更改它是有意义的。因此,假设您在启用短路评估的情况下进行编译,那么当且仅当第一个操作数的评估结果为 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
的评估是运行时错误。通过短路评估,没有运行时错误。
确实,这个具体示例是应启用短路评估的最佳原因之一。否则这样的代码会过于冗长。
【讨论】:
是的,我已启用短路编译选项(项目 > 选项 > 编译器 > 完整布尔评估 = 关闭)。我知道编译应该是一样的,但是使用函数你可以很容易地测试编译器做了什么。很想知道是否有一种聪明的方法可以用参数证明这一点。 是的,谢谢你的例子。尝试了两个编译器选项,它按预期工作或失败。我做了一个小的修改,使示例更加清晰(希望你也这么认为)。短路编译器选项绝对值得推荐……现在我理解多了! 这个例子需要一些小的调整才能在 Delphi7 中编译。记录“结束”后需要一个分号。不支持变量初始化 (n: Integer = 5;)。再次感谢。 感谢分号更正。变量初始化很好。根据我的代码,它必须是全球性的。问题中的代码是一个完整的程序记住。所以 P 是一个全局变量。将其粘贴到 .dpr 文件中就可以了。 啊,是的,P 是全局的。我将它作为函数的局部变量进行了测试。再次感谢。【参考方案2】:设置断点
if (SomeObj1.bNaughtyGlobal1) and (SomeObj2.bNaughtyGlobal2) then
现在运行你的程序到断点。 打开 CPU 窗口(查看->调试窗口->CPU)并逐步执行处理器指令。 在那里您将看到跳转指令,并且您还将看到如果 SomeObj1.bNaughtyGlobal1 为 false 则不会评估其他任何内容,而不是您的 SomeObj2 对象。
【讨论】:
刚刚试了一下,效果很好!不太熟悉汇编程序,但我能够看到两个“cmp”语句,第二个被跳过了。感谢您的提示! @AlainD 有趣的是,如果您关闭短路评估,您将看到不同的机器代码。 是的,很好看。我可以看到,当短路关闭时,两个“cmp”语句将在“jmp”被命中之前运行。【参考方案3】:设置SomeObj1.bNaughtyGlobal1 := False
和SomeObj2 := nil
。如果编译器行为不端并评估 and
表达式的两边,那么当您的程序尝试从空引用中读取 bNaughtyGlobal2
值时,您将遇到访问冲突。
【讨论】:
很好,实际上是在发布问题大约 30 分钟后想到的。以上是关于Delphi中if语句的评估顺序的主要内容,如果未能解决你的问题,请参考以下文章