【发布时间】:2021-05-15 20:49:48
【问题描述】:
在以下示例中:
int main(void) {
int a=7;
{
int a=8;
}
}
生成的程序集将是这样的(来自 Compiler Explorer),无需优化:
main:
pushq %rbp
movq %rsp, %rbp
movl $7, -4(%rbp) // outer scope: int a=7
movl $8, -8(%rbp) // inner scope: int a=8
movl $0, %eax
popq %rbp
ret
如果有重复命名的变量,编译器如何知道变量在哪里?也就是说,在内部范围内时,内存地址为%rbp-8,而在外部范围内时,地址为%rbp-4。
【问题讨论】:
-
"编译器是怎么知道的" 因为语言需要它。编译器如何实现这是一个不同的问题,并且没有普遍有效的答案,因为这是每个实现都可以以自己的方式做出的选择。
-
一个示例实现是使用链表解决冲突的哈希表。
-
或者编译器为每个作用域创建某种标签,并保留一个变量表,其键是对
(identifier, scope-tag)。 -
进入一个新的作用域,编译器可以在堆栈中添加新的符号,在创建时发现同一层的冲突,在引用时发现所有层的冲突。
-
这就是 gcc 提供
-Wshadow编译器选项的原因——以确保您捕获任何阴影变量并避免它们,或者确认它们不会导致未指定的程序值。 (大多数编译器提供类似的选项)
标签: c assembly scope compiler-construction