程序的全局作用域声明变量 x,函数内部又声明了同名局部变量 x。在函数体内引用 x 时,编译器进行符号表查找的正确策略是()。
遵循词法作用域的语言通常从当前作用域开始向外层逐级查找名称。函数内部的局部 x 会遮蔽外层全局 x,因此函数体内未加限定的 x 绑定到局部声明;离开该局部作用域后,外层 x 的绑定仍然有效。
选项分析
正确。由内向外查找能实现词法作用域中的就近绑定和变量遮蔽。
错误。若全局名称永远优先,局部同名声明就无法产生正常的遮蔽效果。
错误。两个声明具有不同作用域和存储位置,不能因名称相同而合并。
错误。名称解析依据作用域规则和声明关系,与变量名长度无关。
本题为什么容易错
遮蔽经常被误解成“局部变量把全局变量删了”。编译器只是让当前引用优先绑定到内层条目;退出作用域后,内层条目失效,外层绑定重新可见。
简短答案
嵌套作用域中出现同名变量时,符号表怎么查找,正确答案是 A(从当前最内层作用域向外查找,先找到局部 x 即停止)。遵循词法作用域的语言通常从当前作用域开始向外层逐级查找名称。函数内部的局部 x 会遮蔽外层全局 x,因此函数体内未加限定的 x 绑定到局部声明;离开该局部作用域后,外层 x 的绑定仍然有效。
易混淆概念对比表
| 概念 | 本题判断 | 区别要点 | 记忆提示 |
|---|---|---|---|
| 从当前最内层作用域向外查找,先找到局部 x 即停止 | 本题正确答案 | 正确。由内向外查找能实现词法作用域中的就近绑定和变量遮蔽。 | 看到题干核心场景时优先联想到它 |
| 始终优先选择全局作用域中的 x | 本题干扰项 | 错误。若全局名称永远优先,局部同名声明就无法产生正常的遮蔽效果。 | 看到该词不要急着选,先判断是否真正解决题干问题 |
| 把两个 x 自动合并为同一个变量 | 本题干扰项 | 错误。两个声明具有不同作用域和存储位置,不能因名称相同而合并。 | 看到该词不要急着选,先判断是否真正解决题干问题 |
| 只按变量名长度决定使用哪个声明 | 本题干扰项 | 错误。名称解析依据作用域规则和声明关系,与变量名长度无关。 | 看到该词不要急着选,先判断是否真正解决题干问题 |
本题易混淆选项怎么区分
- 始终优先选择全局作用域中的 x:错误。若全局名称永远优先,局部同名声明就无法产生正常的遮蔽效果。
- 把两个 x 自动合并为同一个变量:错误。两个声明具有不同作用域和存储位置,不能因名称相同而合并。
- 只按变量名长度决定使用哪个声明:错误。名称解析依据作用域规则和声明关系,与变量名长度无关。
知识点详解
符号表为语义分析和代码生成保存标识符属性,例如类型、作用域层次、存储位置、参数信息和声明位置。嵌套作用域可用符号表栈、作用域链或带层次标记的散列表实现。名称查找从当前层开始,未找到再沿外层环境继续;内层同名声明会遮蔽外层条目,退出内层作用域后再恢复外层绑定的可见性。
备考速记
名字从里往外找,先遇到谁就绑定谁;遮蔽不等于删除。
变量遮蔽在变量遮蔽场景中的作用
变量遮蔽在本题中的核心价值,是解决“程序的全局作用域声明变量 x,函数内部又声明了同名局部变量 x。在函数体内引用 x 时,编译器进行符号表查找的正确策略是()”这个场景问题。复习时不要只背选项名称,还要理解它为什么适用于该场景,以及它能解决哪类安全、流程或管理问题。
同类题怎么考
- 给出全局、函数和代码块三级同名声明,判断某处引用绑定到哪个变量。
- 考查进入或退出作用域时符号表条目的建立与恢复。
- 询问符号表通常保存名称、类型、作用域、偏移量和参数信息中的哪些属性。
变量遮蔽在软件设计师软考中的考法
软考选择题通常不会只考概念定义,还会把变量遮蔽放到变量遮蔽场景中,要求判断它的作用、适用范围或与相近概念的区别。遇到这类题时,先抓住题干中的业务场景,再看哪个选项最能解决该场景下的核心问题。
解题思路
查名字像从当前房间往外找人:本房间已经有一个 x,就按这个声明解释,不必跑到整栋楼的大厅找全局 x。所谓遮蔽只是当前区域优先看到内层名字,外层变量并没有消失。
考点定位
嵌套词法作用域采用由内向外的名称查找;内层同名声明遮蔽外层声明,但不会删除或合并外层符号表条目。
易错提醒
- 把同名声明当成重复定义,却没有区分它们是否位于不同作用域。
- 误认为退出函数后需要重新创建全局符号表条目。
- 只保存变量名,不记录类型、作用域层次和存储位置等属性。
备考提示
- 用栈式作用域表理解进入和退出代码块:进入时压入一层,退出时弹出一层。
- 碰到同名变量题,先标出每个声明所在的大括号范围,再从引用位置向外找最近声明。
你可能还想了解
- 局部变量遮蔽全局变量是什么意思?
- 退出局部作用域后,全局变量为什么还能恢复可见?
- 符号表通常保存标识符的哪些属性?
- 符号表栈怎样支持嵌套代码块?
本文小结
嵌套词法作用域中的名称查找应从当前最内层向外进行。函数局部 x 会遮蔽全局 x,但不会删除它;离开局部作用域后,外层绑定仍可继续使用。