我有一个程序。
int i=10;
main()
{
extern int i;
{
int i=20;
{
const volatile unsigned i=30;
printf("%d ",i);
}
printf("%d ",i);
}
printf("%d\n",i);
}
输出:30 20 10
当我看到这个程序时,我认为这个程序会出错。因为,我们无法创建具有相同名称的符号(变量)。即使我们在块下创建符号,它也已创建为全局符号。
编译器如何区分具有相同名称的全局符号和本地符号?
答案 0 :(得分:3)
您将此与One Definition规则混淆,后者基本上指出在单个翻译单元中,单个对象不能具有多于(或少于)一个定义。
但那不是你在这里做的。你正在做的是创建两个碰巧具有相同名称的对象。即使不是一个好主意,这也是语言所允许和明确定义的。
int i=10;
main()
{
{
int i=20;
{
const volatile unsigned i=30;
}
}
}
在此代码中,您首先将i
定义为全局。然后,在块作用域内定义一个名为i
的新变量。在该块范围内,本地定义的i
隐藏全局定义的定义。您仍然可以通过::i
引用全球定义的那个。
然后在更深的块中定义另一个名为i
的变量。这个也隐藏了前两个具有相同名称的变量。
不要写这样的代码。
答案 1 :(得分:1)
因为我们无法创建具有相同名称的符号(变量)。
我们可以在不同的范围内声明具有相同名称的变量。
编译器如何区分具有相同名称的全局符号和本地符号?
当块内的声明命名为已经可见(因为它有文件范围或因为它在封闭块中声明)的标识符时,新声明暂时隐藏旧的,标识符具有新的含义。在块结束时,标识符恢复其旧的含义。
答案 2 :(得分:1)
因为,我们无法创建具有相同名称的符号(变量)。
是的,我们可以,只要它们不在同一范围内。如果在这里,一个是在嵌套范围内,那么它会在外部范围内隐藏声明。
编译器如何区分具有相同名称的全局符号和本地符号?
首先查看当前块的范围,然后查看包含该块的块,依此类推,直到找到声明或无法在全局命名空间中找到声明。 (在C ++中,由于类范围和命名空间,事情有点复杂;但一般原则是相同的。)
答案 3 :(得分:0)
我认为编译器会构建一个包含名称空间和块的树,并开始在树的给定级别向其根目录搜索非限定名称。
答案 4 :(得分:0)
编译器总是使用最里面的“scope”(这实际上意味着“阻塞”)的声明。
一旦宣布了一个新的,外部的那些是不可访问的(除非你拿了一个指针)。
答案 5 :(得分:0)
块内的变量有自己的范围,即它在块内部保留的内容 因此,如果我们在块之外创建另一个变量(具有相同的名称),它将拥有自己的范围
答案 6 :(得分:0)
因为我们无法创建具有相同名称的符号(变量)。
您的内部变量是本地变量,它的优先级高于全局变量。你可以拥有全局和本地,但是在块中有使用的局部变量。