-3

我有一个程序。

   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

当我看到这个程序时,我以为这个程序会报错。因为,我们不能创建同名的符号(变量)。即使我们在块下创建符号,它已经被创建为全局符号。

编译器如何区分同名的全局符号和局部符号?

4

7 回答 7

3

您将此与单一定义规则混淆了,该规则基本上指出,在单个翻译单元中,单个对象的定义不能多于(或少于)一个。

但这不是你在这里做的。您正在做的是创建两个恰好具有相同名称的对象。如果不是一个好主意,那是语言允许并明确定义的。

int i=10;
   main()
   {
         {
                int i=20;
                {
                     const volatile unsigned i=30;
                }
          }
   }

在此代码中,您首先将其定义i为全局。i然后,您定义一个也在块范围内命名的新变量。在该块范围内,本地定义i 隐藏了全局定义的定义。您仍然可以通过::i.

然后,您定义另一个变量,该变量也在i更深的块中命名。这个也隐藏了前两个同名的变量。

不要写这样的代码。

于 2013-11-06T14:53:03.113 回答
1

因为,我们不能创建同名的符号(变量)。

我们可以在不同的范围内声明具有相同名称的变量。

编译器如何区分同名的全局符号和局部符号?

当块内的声明命名一个已经可见的标识符时(因为它具有文件范围或因为它在封闭块中声明),新的声明会暂时隐藏旧的声明,并且标识符具有新的含义。在块的末尾,标识符恢复了它的旧含义。

于 2013-11-06T14:49:56.483 回答
1

因为,我们不能创建同名的符号(变量)。

是的,我们可以,只要它们不在同一范围内。如果像这里一样,一个在嵌套范围内,则它将声明隐藏在外部范围中。

编译器如何区分同名的全局符号和局部符号?

首先查看当前块的范围,然后查看包含该块的块,依此类推,直到找到声明或在全局命名空间中找不到声明。(在 C++ 中,由于类作用域和命名空间,事情有点复杂;但一般原则是相同的)。

于 2013-11-06T14:50:49.883 回答
0

我认为编译器构建了一个封闭的命名空间和块树,并开始在树的给定级别向其根搜索不合格的名称。

于 2013-11-06T14:50:13.250 回答
0

编译器总是使用最里面的封闭“范围”(实际上是“块”)的声明。

一旦你声明了一个新的,外部的就无法访问(除非你拿了一个指针)。

于 2013-11-06T14:51:19.097 回答
0

块内的变量有自己的范围,即它所做的任何事情都保留在该块内,因此如果我们在块外创建另一个变量(同名),它将有自己的范围

于 2013-11-06T14:54:35.760 回答
0

因为,我们不能创建同名的符号(变量)。

您的内部变量是本地变量,它比全局变量具有更高的优先级。您可以同时使用全局和本地,但是在块中使用局部变量。

于 2013-11-06T14:55:08.013 回答