Delphi 编译器指令反向求值参数

2023-12-09

这个使用 Math.pas 中的 IFThen 函数的 delphi 两行代码给我留下了深刻的印象。但是,它首先评估 DB.ReturnFieldI,这很不幸,因为我需要调用 DB.first 来获取第一条记录。

DB.RunQuery('select awesomedata1 from awesometable where awesometableid = "great"');
result := IfThen(DB.First = 0, DB.ReturnFieldI('awesomedata1'));

(作为一个毫无意义的澄清,因为我已经得到了很多好的答案。我忘了提到 0 是 DB.First 返回的代码,如果它里面有东西,否则可能没有意义)

显然这不是什么大问题,因为我可以让它与五个坚固的衬里一起工作。但要使其工作,我所需要的只是让 Delphi 首先评估 DB.first,然后评估 DB.ReturnFieldI。我不想更改 math.pas,而且我认为这不能保证我重载 ifthen,因为大约有 16 个 ifthen 函数。

只要让我知道编译器指令是什么,是否有更好的方法来做到这一点,或者如果没有办法做到这一点,并且任何其过程是调用 db.first 并盲目检索他发现的第一件事的人都不是一个真正的程序员。


表达式的求值顺序通常是不明确的。 (C 和 C++ 的方式相同。Java 始终从左到右计算。)编译器无法对其进行控制。如果您需要按特定顺序计算两个表达式,请以不同的方式编写代码。我真的不会担心代码行数。线路便宜;根据需要使用多个。如果您发现自己经常使用这种模式,请编写一个将其全部包装起来的函数:

function GetFirstIfAvailable(DB: TDatabaseObject; const FieldName: string): Integer;
begin
  if DB.First = 0 then
    Result := DB.ReturnFieldI(FieldName)
  else
    Result := 0;
end;

即使评估顺序不同,您的原始代码也可能不是您想要的。即使DB.First wasn't等于零,调用ReturnFieldI还是会被评价的。所有实际参数在调用使用它们的函数之前都会被完全评估。

无论如何,改变 Math.pas 对你没有帮助。它不控制其实际参数的评估顺序。当它看到它们时,它们已经被评估为布尔值和整数;它们不再是可执行表达式。


调用约定可能会影响评估顺序,但仍然不能保证。将参数压入堆栈的顺序不需要与确定这些值的顺序相匹配。事实上,如果您发现 stdcall 或 cdecl 为您提供了所需的评估顺序(从左到右),那么它们将在相反的顺序与他们一起通过的那个人。

The pascal调用约定在堆栈上从左到右传递参数。这意味着最左边的参数是堆栈底部的参数,最右边的参数位于顶部,就在返回地址的下方。如果IfThen函数使用该调用约定,编译器可以通过多种方式实现该堆栈布局:

  1. 正如您所期望的那样,每个参数都会被立即求值并推送:

    push (DB.First = 0)
    push DB.ReturnFieldI('awesomedata1')
    call IfThen
    
  2. 从右到左计算参数并将结果存储在临时变量中,直到它们被推送:

    tmp1 := DB.ReturnFieldI('awesomedata1')
    tmp2 := (DB.First = 0)
    push tmp2
    push tmp1
    call IfThen
    
  3. 首先分配堆栈空间,然后以方便的顺序进行计算:

    sub esp, 8
    mov [esp], DB.ReturnFieldI('awesomedata1')
    mov [esp + 4], (DB.First = 0)
    call IfThen
    

请注意IfThen receives在所有三种情况下,参数值的顺序相同,但函数不一定按该顺序调用。

默认的寄存器调用约定也从左到右传递参数,但适合的前三个参数在寄存器中传递。不过,用于传递参数的寄存器也是最常用于计算中间表达式的寄存器。的结果DB.First = 0需要在 EAX 寄存器中传递,但编译器还需要该寄存器来调用ReturnFieldI并用于调用First。首先评估第二个函数可能更方便一些,如下所示:

call DB.ReturnFieldI('awesomedata1')
mov [ebp - 4], eax // store result in temporary
call DB.First
test eax, eax
setz eax
mov edx, [ebp - 4]
call IfThen

另一件需要指出的是,您的第一个参数是复合表达式。有一个函数调用和比较。没有什么可以保证这两个部分是连续执行的。编译器可能会首先通过调用来消除函数调用First and ReturnFieldI,然后比较First返回值为零。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Delphi 编译器指令反向求值参数 的相关文章

  • FreeMM 与 ShareMem

    我们有很多用 delphi 和 c builder 编写的 dll 库 并使用 sharemem 和 borlndmm dll 3d party 库中的对齐问题迫使我们转向 delphi 2007 中的新内存管理器 有人可以帮我解释一下 共
  • EIdOSSLUnderlyingCryptoError 和“使用 SSL 连接时出错。错误:14094410...”

    我在 OS X 上的 Delphi 10 1 Berlin 中遇到 Indy 组件问题 我正在使用TIdHTTP使用 HTTPS 连接到 Web 服务 问题是从 OS X 客户端连接到服务器 在 OS X 上运行时 我总是遇到同样的错误 P
  • Delphi - 相当于C#的三元运算符? [复制]

    这个问题在这里已经有答案了 可能的重复 Delphi 中是否存在或者将来是否存在条件运算符 https stackoverflow com questions 2108609 is there or is there ever going
  • Delphi 的免费加密库 [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在为 Delphi 2010 寻找一个免费且最新的加密库 该库实现 RSA 和 AES Rijnda
  • Delphi 2007 中的 HelpInsight 文档

    我正在使用 D2007 并尝试使用 HelpInsight 功能 自 D2005 起提供 来记录我的源代码 我主要对让 HelpInsight 工具提示正常工作感兴趣 通过各种网上冲浪和实验 我发现了以下内容 使用三斜杠 注释样式比其他记录
  • 在 Delphi 2009 上安装最新版本的 Indy 10 [重复]

    这个问题在这里已经有答案了 是否有更新 Delphi 2009 中的 Indy 10 组件的分步指南 我读过正在卸载线程 https stackoverflow com questions 486210 what is the proper
  • 如何向标准集合编辑器添加图标?

    我有一个自定义控件 它利用TCollection and TCollectionItem 在集合编辑器中 我想向每个列表项添加图标 该列表项由内部TImageList 在其父组件内 集合项本身代表图标 我想在这个编辑器中显示相应的图标 如何
  • DELPHI 和 WANT 或 NANT

    We use 巡航控制 net http confluence public thoughtworks org display CCNET Welcome to CruiseControl NET在 Delphi 2006 应用程序中进行持
  • Delphi 5 的哈希表实现 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 您知道 Delphi 5 的良好且免费的哈希表实现吗 我需要在哈希表中组织大量数据 并且我有点担心在网
  • Delphi 流畅的界面

    使用上有什么优点和缺点流畅的界面 http en wikipedia org wiki Fluent interface在德尔福 流畅的界面应该会增加可读性 但我对此有点怀疑one包含很多链式方法的长 LOC 是否存在编译器问题 是否存在任
  • 是否可以声明长度受限且不从 0/1 开始的字符串类型?

    在 Delphi 中 可以声明整数值的子范围 例如 type myInt 2 150 它将 myInt 类型的值限制为 2 到 150 之间的值 但是如果我想限制字符串的长度怎么办 如果我写 type myString string 150
  • 打印 TDBGrid [重复]

    这个问题在这里已经有答案了 如何在不安装或下载组件的情况下打印 DBGrid OR 如何将 DBGrid 的数据放入 RichEdit 以便我可以从那里打印它 数据感知控件从 DataSource 属性获取数据 并使用它 不过 您必须手动遍
  • 如何在iOS的Delphi程序中使用IPv6协议

    我尝试在我的移动程序中使用 IPv6 协议 我的服务器位于 NAT 后面的 LAN 内 在服务器上我使用IP端口3000 我已经组织了从路由器端口 45500 到服务器端口 3000 的虚拟服务器 端口转发 在服务器上 我运行 ipconf
  • 如何比较枚举类型集

    从某个时刻开始 我厌倦了编写设定条件 and or 因为对于更多的条件或更长的变量名 重新编写会变得笨拙且烦人 所以我开始写助手这样我就可以写ASet ContainsOne ceValue1 ceValue2 代替 ceValue1 in
  • logback的“谨慎模式”是如何实现的?

    The 审慎模式 http logback qos ch manual appenders html prudentlogback 中的序列化所有 JVM 之间的 IO 操作 写入同一文件 可能运行在不同的主机上 在其他日志记录框架中 如果
  • 如何从该 JAVA 文件中提取 Delphi 类以与 Android 一起使用?

    我的Delphi XE7项目需要与FTDI FT311 Android 配件芯片 http www ftdichip com Products ICs FT311D html 他们帮助提供了一个 Android 演示 其中包括他们的 JAV
  • Delphi - 如果没有创建类,为什么这个函数可以工作?

    考虑这个类 unit Unit2 interface type TTeste class private texto string public function soma a b integer string end implementa
  • H2161 重复资源[一个VCL项目可以有2个类名相同但命名空间不同的表单吗?]

    我尝试在 2 个不同的命名空间中创建具有相同类名的 2 个表单 FirstNameSpace ExampleFormName TExampleFormName SecondNameSpace ExampleFormName TExample
  • 从其可执行文件的路径获取服务名称

    我有一个可执行文件的路径 它是一个正在运行的服务应用程序 例如 C Program Files x86 Someapp somesvc exe 我想停止并启动它 为此我想我需要获取服务的名称 如下所示 this https stackove
  • 如何在表单上绘制半透明图像?

    我想在 Delphi 窗体上绘制半透明图像 但由于某种原因它不起作用 Here is the original PNG border is semi transparent 我将图像加载到TImage object Image1 Trans

随机推荐

  • Google Apps 脚本:“错误 401:deleted_client OAuth 客户端已删除”突然?

    我目前在 Google Sheets 上使用 Google App Scripts 作为我的预算电子表格 本质上 我的设置方式是 Buy item 将费用输入 Google 表单 输入电子表格 使用 Apps 脚本将时间戳转换为 yyyy
  • 我如何有条件地要求使用 AngularJS 进行表单输入?

    假设我们正在使用 AngularJS 构建一个地址簿应用程序 人为的示例 我们有一个联系人表单 其中包含电子邮件和电话号码的输入 我们希望要求非此即彼 but not both 我们只想要email如果需要输入phone输入为空或无效 反之
  • d3:当鼠标悬停事件时,多系列折线图每行的工具提示

    我正在 Angular 2 应用程序中使用 d3 绘制图表 现在我有一个多系列折线图 因此我尝试在将鼠标悬停在其垂直位置时在每条线上添加工具提示 export class LineGraphDirective private host pr
  • 如何使用 HttpClient.PostAsync 发送大数据文件? [复制]

    这个问题在这里已经有答案了 我的功能如下 对于 25MB 左右的任何内容 它都可以很好地工作 但大于该值 它就会停止工作 当我说停止工作时 它不会抛出任何异常并且失败noserver函数底部的结果选项 我似乎找不到任何涉及任何其他缓冲区大小
  • 如何在 Spring Boot 中使用 Spring Web Services 动态 WSDL 生成?

    我跟着Spring Web 服务入门教程我已经整理了一个示例 Web 应用程序 可以在以下位置动态生成 W SDL ws holiday wsdl端点为请求提供服务 ws holidayService 到目前为止 一切都很好 现在我正在将该
  • 计算两条路径的交叉面积

    只有一个Raphael pathIntersection path1 path2 效用于Rapha l库 而这个方法只能获取交叉点这 2 条路径中 我需要的是交叉区域 如下图所示 该方法仅得到2分 用红色圆圈标记 我希望同时有另外 2 个点
  • 绝对路径和相对路径

    使用任何 Web 服务器或 Tomcat 时 绝对路径和相对路径有什么区别 绝对路径以 开头 指的是从当前站点 或虚拟主机 的根目录开始的位置 相对路径不以 开头 而是引用所引用文档的实际位置中的位置 示例 假设根是http foo com
  • 添加小数点时,ios 在字典上使用双引号

    我正在与 JSON 交互 对于 get 它工作正常 但是对于 post 我有一个错误 因为字典对象用双引号 引起来 对于网络服务 我收到双引号错误 问题是 如果我使用点来表示小数点 则会出现双引号 NSMutableDictionary d
  • 如何在 IPython 笔记本中隐藏 [重复]

    这个问题在这里已经有答案了 我正在绘制一个 NumPy 值数组 I 使用 IPython 笔记本 matplotlib使用绘图命令的内联模式plt plot I o 结果输出是
  • 使用生成的主键插入 Derby 表时,Eclipselink JPA 出现错误

    当使用生成的主键持久保存到表中时 EclipseLink 似乎错误地将空主键值传递给 Derby 德比返回错误尝试修改标识列在这种情况下 Derby 需要一条排除 id 值的 SQL 语句 我的问题是如何强制 EclipseLink 发送正
  • JavaScript 中处理大数 (BigNum) 的标准解决方案是什么?

    JavaScript 或浏览器中是否内置了 bignum 另一种方法是加载外部库 例如 但这似乎很慢并且可能会触发安全警告 我考虑过自己的基础http github com silentmatt javascript biginteger
  • 忽略基类 使用 Dokka 查看子类文档中的公共函数

    我使用 Dokka 为 View 子类生成了文档 效果很好 但文档包含基本 View 类的数百个公共函数 有没有办法只记录我的子类公共函数 我尝试将这些选项添加到 Gradle 任务中 但我不认为这就是它的用途 dokkaHtml dokk
  • 使用 EF Core Linq2Sql 进行聚合的聚合

    我有一个带有 EF Core 2 2 Code First DB 的 ASP NET Core 2 2 项目 我有以下实体 建筑物 基本上是一个带有一些其他重要数据的地址 Floor 包含楼层号 一栋建筑物可以有多层 一个楼层必须恰好有一个
  • 如何解释await/async同步上下文切换行为

    关于以下代码的行为 有几件事 但有一件主要的事情 我不明白 有人可以帮忙解释一下吗 它实际上是非常简单的代码 只是一个调用异步方法的常规方法 在异步方法中 我使用 using 块来尝试临时更改 SynchronizationContext
  • 从 JSP 返回 JSONP 而不是 JSON

    I found 这个问题从jsp将响应类型设置为json 但我需要将响应类型设置为jsonp以进行跨域访问 还会是这样吗 response setContentType application javascript 并将来自jsp的响应包装
  • 如何使用 R8 在堆栈跟踪中保留原始行号?

    我正在尝试找出如何使用 R8 保留原始行号 使用当前的AndroidStudio制作应用程序并使用R8对其进行混淆 甚至上传mapping txt将文件上传到 Google Play Console 后 用户的堆栈跟踪在某些情况下是无用的
  • T-SQL 中的编辑距离

    我对 T SQL 计算 Levenshtein 距离的算法感兴趣 我在 TSQL 中实现了标准 Levenshtein 编辑距离函数 并进行了多项优化 与我所知的其他版本相比 速度有所提高 如果两个字符串的开头有共同的字符 共享前缀 结尾有
  • 无法使最大宽度与 Bootstrap 下拉菜单一起使用

    我有一个 Bootstrap 下拉菜单 在某些情况下 菜单项可能非常大 所以我需要设置一个max width 另外 我不希望菜单项被剪切 所以我必须使用white space normal也 问题是我的max width被完全忽略 如果我设
  • File.Copy 与手动 FileStream.Write 复制文件

    我的问题是关于文件复制性能 我们有一个媒体管理系统 需要将文件系统上的大量文件移动到不同位置 包括同一网络上的 Windows 共享 FTP 站点 AmazonS3 等 当我们都在一个 Windows 网络上时 我们可以使用System I
  • Delphi 编译器指令反向求值参数

    这个使用 Math pas 中的 IFThen 函数的 delphi 两行代码给我留下了深刻的印象 但是 它首先评估 DB ReturnFieldI 这很不幸 因为我需要调用 DB first 来获取第一条记录 DB RunQuery se