我有一个程序。
int i=10;
main()
{
extern int i;
{
int i=20;
{
const volatile unsigned i=30;
printf("%d ",i);
}
printf("%d ",i);
}
printf("%dn",i);
}
输出:30 20 10
当我看到这个程序时,我认为这个程序会给出错误。因为,我们不能创建一个同名的符号(变量)。即使我们在块下创建符号,它已经被创建为全局符号。
编译器如何区分全局符号和同名的局部符号?
您将此与"一个定义"规则混淆了,该规则基本上指出,在单个翻译单元中,单个对象不能具有更多(或更少)一个定义。
但这不是你在这里做的事情。 您正在做的是创建两个恰好具有相同名称的对象。 这是语言允许和明确定义的,如果不是好主意的话。
int i=10;
main()
{
{
int i=20;
{
const volatile unsigned i=30;
}
}
}
在此代码中,首先将i
定义为全局。 然后,在块范围内定义一个名为 i
的新变量。 在该块范围内,本地定义的i
隐藏全局定义的定义。 您仍然可以通过 ::i
引用全局定义的一个。
然后,在更深的块中定义另一个也命名为 i
的变量。 这个还隐藏了具有相同名称的前两个变量。
不要这样写代码。
因为,我们不能创建一个同名的符号(变量)。
我们可以在不同的范围内声明具有相同名称的变量。
编译器如何区分全局符号和同名的局部符号?
当块内的声明命名已可见的标识符时(因为它具有文件范围或在封闭块中声明),新声明会暂时隐藏旧声明,并且标识符具有新的含义。在块的末尾,标识符恢复其旧的含义。
因为,我们不能创建一个同名的符号(变量)。
是的,我们可以,只要它们不在同一范围内。如果像这里一样,一个位于嵌套作用域中,则它将声明隐藏在外部作用域中。
编译器如何区分全局符号和同名的局部符号?
首先查看当前块的范围,然后查看包含该块的块,依此类推,直到它找到声明或在全局命名空间中找不到声明。(在C++中,由于类作用域和命名空间的原因,事情有点复杂;但一般原则是相同的)。
我认为编译器构建了一个包含封闭命名空间和块的树,并开始在树的给定级别向其根搜索非限定名称。
编译器始终使用最内层封闭的"范围"(实际上意味着"块")的声明。
一旦你声明了一个新的,外部的就无法访问了(除非你采取了指针)。
块内的变量有自己的作用域,即无论它做什么都保留在该块内因此,如果我们在块外创建另一个变量(具有相同的名称),它将有自己的范围
因为,我们不能创建一个同名的符号(变量)。
您的内部变量是局部变量,其优先级高于全局变量。您可以同时拥有全局和局部,但是在块中使用局部变量。