软件设计师 · 高频练习

布尔表达式中间代码为什么要使用回填技术?

中级 单选题 第 849 题 中等 软件设计师编译原理中间代码回填布尔表达式短路求值
题目

编译器为布尔表达式生成跳转式中间代码时,某些条件跳转的目标基本块尚未生成。回填技术的主要作用是()。

A 在程序运行时修改源代码中的条件表达式
B 把所有条件跳转改成无条件跳转
C 提前执行真假两个分支,再选择保留结果
D 先记录目标未定的跳转指令链表,目标确定后统一填写地址
题目类型:原创高频练习题 用途:用于帮助理解软件设计师相关考点和答案解析,不等同于官方真题。
正确答案
D
答案解析

单遍生成中间代码时,条件跳转指令可能先出现,而目标基本块的入口地址要到后面才知道。编译器先把这些未定目标指令的编号组织成 true list 或 false list,待目标地址确定后,用 backpatch 一次性填入。

选项分析

A

错误。回填发生在编译生成中间代码阶段,不是运行时自修改源代码。

B

错误。条件跳转仍保留真假选择,回填只补目标地址。

C

错误。短路布尔代码依靠控制流选择分支,不需要先执行两个分支。

D

正确。回填先挂起未知目标,再在地址确定时补齐跳转字段。

本题为什么容易错

“回填”听起来像程序运行时补数据,容易和动态链接、自修改代码混淆。它本质是编译器在尚不知道标签地址时留下待办项,随后完成控制流连接。

先看结论

简短答案

布尔表达式中间代码为什么要使用回填技术,正确答案是 D(先记录目标未定的跳转指令链表,目标确定后统一填写地址)。单遍生成中间代码时,条件跳转指令可能先出现,而目标基本块的入口地址要到后面才知道。编译器先把这些未定目标指令的编号组织成 true list 或 false list,待目标地址确定后,用 backpatch 一次性填入。

解析

易混淆概念对比表

概念本题判断区别要点记忆提示
在程序运行时修改源代码中的条件表达式 本题干扰项 错误。回填发生在编译生成中间代码阶段,不是运行时自修改源代码。 看到该词不要急着选,先判断是否真正解决题干问题
把所有条件跳转改成无条件跳转 本题干扰项 错误。条件跳转仍保留真假选择,回填只补目标地址。 看到该词不要急着选,先判断是否真正解决题干问题
提前执行真假两个分支,再选择保留结果 本题干扰项 错误。短路布尔代码依靠控制流选择分支,不需要先执行两个分支。 看到该词不要急着选,先判断是否真正解决题干问题
先记录目标未定的跳转指令链表,目标确定后统一填写地址 本题正确答案 正确。回填先挂起未知目标,再在地址确定时补齐跳转字段。 看到题干核心场景时优先联想到它
本题易混淆选项怎么区分
  • 在程序运行时修改源代码中的条件表达式:错误。回填发生在编译生成中间代码阶段,不是运行时自修改源代码。
  • 把所有条件跳转改成无条件跳转:错误。条件跳转仍保留真假选择,回填只补目标地址。
  • 提前执行真假两个分支,再选择保留结果:错误。短路布尔代码依靠控制流选择分支,不需要先执行两个分支。
复习

知识点详解

控制流语句和短路布尔表达式常包含向前跳转。单遍翻译时,目标语句尚未生成,编译器无法立即填写跳转地址,于是用链表记录所有待定指令。目标入口确定后,backpatch 将同一链表中的地址字段统一填为该入口。对 E1 and E2,E1 的真出口通常回填到 E2 入口;对 E1 or E2,E1 的假出口通常回填到 E2 入口,这正体现短路求值。

备考速记

地址未知先挂账,入口确定再沿链表统一补上。

短路求值在短路求值场景中的作用

短路求值在本题中的核心价值,是解决“编译器为布尔表达式生成跳转式中间代码时,某些条件跳转的目标基本块尚未生成。回填技术的主要作用是()”这个场景问题。复习时不要只背选项名称,还要理解它为什么适用于该场景,以及它能解决哪类安全、流程或管理问题。

拓展

同类题怎么考

  • 给出布尔表达式,判断 true list 和 false list 如何合并与回填。
  • 根据 if、if-else、while 的中间代码确定某链表回填到哪个入口。
  • 结合短路求值解释为什么无需先计算完整布尔值。
短路求值在软件设计师软考中的考法

软考选择题通常不会只考概念定义,还会把短路求值放到短路求值场景中,要求判断它的作用、适用范围或与相近概念的区别。遇到这类题时,先抓住题干中的业务场景,再看哪个选项最能解决该场景下的核心问题。

解题思路

把它想成老师先写“答错的同学去第____页订正”,页码还没排出来,就把所有空格位置记在一张清单上。等订正页确定,再沿清单一次填完。回填改的是编译期间的跳转目标,不是程序跑起来以后去改源代码。

考点定位

回填解决向前跳转目标暂时未知的问题:makelist 创建链表,merge 合并链表,backpatch 将链表中指令的目标字段统一填写为已知地址。

易错提醒

  • 把 true list 和 false list 当成布尔值数组,而不是待填目标的跳转指令编号集合。
  • 认为回填会改变条件判断本身,实际上它只补跳转去向。
  • 忽略短路求值中不同布尔运算对真假链表的合并方式不同。

备考提示

  • 画两条虚线:条件为真去哪、为假去哪;目标未知时把指令编号挂到对应链表。
  • 复习 makelist、merge、backpatch 三个操作时,配合 if 和 while 的控制流图理解。

你可能还想了解

  • true list 和 false list 保存的是什么?
  • makelist、merge、backpatch 分别做什么?
  • 回填技术与短路求值有什么关系?
  • if-else 中哪些跳转目标需要延后回填?

本文小结

回填用于处理编译期间尚未确定目标地址的向前跳转。先把待填指令编号放入真假出口链表,等目标基本块入口确定后,再统一补齐跳转地址。