如何在机器级别或内存级别在编译器中实现变量范围
Posted
技术标签:
【中文标题】如何在机器级别或内存级别在编译器中实现变量范围【英文标题】:How is scope of variable implemented in compiler at machine level or memory level 【发布时间】:2012-10-23 09:07:56 【问题描述】:编译器如何实现变量的范围? 我的意思是,当我们说静态变量时,范围仅限于在定义静态变量的同一文件中定义的块或函数? 这是如何在机器级别或内存级别实现的?
这个限制实际上是如何实现的?
在程序运行时如何解决这个范围?
【问题讨论】:
看看这个:- ***.com/questions/898432/… 【参考方案1】:在机器级别根本无法实现。编译器在实际生成机器代码之前检查范围。 C 的规则是由编译器实现的,而不是由机器实现的。编译器必须检查这些规则,机器不会也不能。
编译器如何检查的非常简单的解释:
每当引入一个作用域时,编译器都会给它一个名称并将其放入一个结构(树)中,这样可以很容易地确定该作用域相对于其他作用域的位置,并将其标记为当前范围。声明变量时,将其分配给当前范围。访问变量时,会在当前范围内查找。如果未找到,则查找树以查找当前树之上的范围。这一直持续到我们到达最高范围。如果仍然没有找到变量,那么我们就有了范围冲突。
【讨论】:
【参考方案2】:在编译器内部,定义了它的实现。例如,如果我正在编写一个编译器,我会使用树来定义“范围”,它肯定是二叉树中的符号表。
有些人会使用任意深度的哈希表。它的所有实现都定义了。
【讨论】:
对不起,我对数据结构不太满意...你能用类似的术语解释一下吗 如果你想写一个编译器或者想理解一个@vijaykumar,你必须这样做【参考方案3】:我不是 100% 确定我理解你在问什么,但如果你的意思是“静态变量和函数如何存储在最终程序中”,那是实现定义的。
也就是说,存储此类变量和函数的常用方法与任何其他全局符号(以及一些非全局符号)位于相同的位置——不同之处在于这些不是“导出”的,因此不可见在任何试图链接到我们软件的外部代码中。
换句话说,一个包含以下内容的程序:
int var;
static int svar;
int func() static int func_static; ...
static int sfunc() ...
...在内存中可能有以下布局(假设我们的数据从0xF000
开始,函数从0xFF00
开始):
0xF000: var
0xF004: svar
0xF008: func.func_static
...
0xFF00: func's data
0xFF40: sfunc's data /* assuming we needed 0x40 bytes for `func`! */
然而,导出列表将只包含非静态符号,也就是导出的符号:
var v 0xF000
func f 0xFF00
再次——注意,虽然静态数据仍被写入文件(它必须存储在某个地方!),但它不会被导出;通俗地说,我们的程序不会告诉任何人它包含svar
、sfunc
和类似的内容。
在 Unices 中,您可以使用 nm
工具列出库或程序导出的符号:http://unixhelp.ed.ac.uk/CGI/man-cgi?nm;确实存在适用于 Windows 的类似工具(GnuWin32 可能有类似的工具)。
在实践中,可执行代码通常与数据分开存储(例如,这样可以防止写入),并且它们都可能会重新排序以最大限度地减少内存使用和缓存未命中,但想法保持不变。
当然,可以应用优化——例如,可以在每次调用中内联静态函数,这意味着根本不会为函数本身生成任何代码,因此它不会在任何地方单独存在。
【讨论】:
以上是关于如何在机器级别或内存级别在编译器中实现变量范围的主要内容,如果未能解决你的问题,请参考以下文章
Oracle 12.1新特性----使用RMAN从备份中实现recover table