-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

これは、基本的に単一の翻訳単位では、単一のオブジェクトが複数の (または複数の) 定義を持つことはできないという 1 つの定義ルールと混同しています。

しかし、それはあなたがここでやっていることではありません。あなたがしているのは、たまたま同じ名前を持つ 2 つのオブジェクトを作成することです。素晴らしいアイデアではないにしても、それは言語によって許可され、明確に定義されています。

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

このコードでは、最初iにグローバルとして定義します。i次に、同じくブロック スコープ内で名前が付けられた新しい変数を定義します。そのブロック スコープ内で、ローカルに定義されたものは、グローバルに定義されたものの定義をi 隠します。を介してグローバルに定義されたものを引き続き参照できます::i

i次に、より深いブロックで名前が付けられたさらに別の変数を定義します。これは、同じ名前の前の 2 つの変数も非表示にします。

このようなコードを書かないでください。

于 2013-11-06T14:53:03.113 に答える
1

同じ名前のシンボル(変数)を作成することはできません。

異なるスコープで同じ名前の変数を宣言できます。

コンパイラは、同じ名前のグローバル シンボルとローカル シンボルをどのように区別できますか?

ブロック内の宣言が既に表示されている識別子に名前を付ける場合(ファイル スコープがあるため、または外側のブロックで宣言されているため)、新しい宣言は古い宣言を一時的に非表示にし、識別子は新しい意味を持ちます。ブロックの最後で、識別子は古い意味を取り戻します。

于 2013-11-06T14:49:56.483 に答える
0

ブロック内の変数には独自のスコープがあります。つまり、それが行うことはすべてそのブロック内にとどまるため、ブロック外に別の変数 (同じ名前を持つ) を作成すると、独自のスコープを持つことになります。

于 2013-11-06T14:54:35.760 に答える
0

同じ名前のシンボル(変数)を作成することはできません。

内部変数はローカルであり、グローバル変数よりも優先度が高くなります。グローバルとローカルの両方を持つことができますが、ブロック内にはローカル変数を使用しています。

于 2013-11-06T14:55:08.013 に答える
0

コンパイラは、囲まれた名前空間とブロックのツリーを構築し、ツリーの特定のレベルでルートに向かって非修飾名の検索を開始すると思います。

于 2013-11-06T14:50:13.250 に答える