7
    #include <stdio.h>

    int a;

    void myproc()
    {
        int a = 2;
        while (a == 2)
        {
            int a = 3;
            printf("a = %d\t", a);
            break;
        }
        printf("a = %d\t", a);
    }

    int main()
    {
        a = 1;
        myproc();
        printf("a = %d\t", a);
        return (0);
    }

上記のコードが出力されることを期待していました: a = 3 a = 3 a = 1 しかし、それは出力します: a = 3 a = 2 a = 1 誰かが有効な説明を提供できますか?

4

6 に答える 6

6

ここに説明があります -- 以下の解説を参照してください。

#include <stdio.h>

int a;

void myproc()
{
    int a = 2; // (1) a = 2
    while (a == 2) // true
    {
        int a = 3;  // (2) new scope, new a = 3
        printf("a = %d\t", a); // (X) prints 3 as it gets the 'nearest a' in the scope
        break;
    } // throws away a=3 from (2)
    printf("a = %d\t", a); // (Y) Uses (1) i.e. 2 and print it 
}

int main()
{
    a = 1;
    myproc();
    printf("a = %d\t", a); // (Z) Just prints 1 as the scope is not effected by myproc
    return (0);
}

したがって、これは (X) (Y) と (Z) を出力します

つまり 3 2 1

于 2012-12-22T03:59:07.487 に答える
6

はい、それらはローカル自動変数であり、コンパイラーが特定の最適化 (レジスターへの格納など) を行うことを決定しない限り、特定のスコープに出入りするときにスタックにプッシュおよびポップされます。ただし、特定の変数については、その変数の最もローカルにスコープされたバージョンが、それにアクセスするときに使用されます。たとえば、C89 では、for ループ宣言内でループ カウンターを宣言することを決定した場合、通常、次のコードはコンパイラ エラーを生成します。

for (int i=0; i < N; i++)
    for (int i=0; i < J; i++)
        printf("%d", i);

print の値iは常にi、内側の for ループで宣言されたの値になりますi

于 2012-12-22T03:54:42.333 に答える
3

「ループ内」?

あなたが求めている質問は、ループとはまったく関係ありません。コードにあるものと通常のものとの間に違いはありません

int a;

void myproc()
{
    int a = 2;
    {
        int a = 3;
        printf("a = %d\t", a);
    }
    printf("a = %d\t", a);
}

ネストされた各ブロックには、独自の変数があります。それだけです。そして、それはループとは何の関係もありません。

ループに実際に関連する宣言は、次のように、ループのヘッダーで行われる宣言になります。

    int a = 3;

    for (int a = 0; a < 10; ++a)
    {
      ...
    }

    printf("a = %d\n", a); // <- prints `3`

aヘッダーで宣言されたものforは、まだループに対してローカルです。

于 2012-12-22T04:16:32.417 に答える
2

{ } 変数はスコープを宣言します。これらの中かっこの間で変数を宣言するときと同様に、それらの中かっこでのみ使用できます。ネストされた変数がある場合 ( myproca = 2 を宣言し、ループ内で a=3 のように)、現在のスコープに最も近いと宣言された変数が参照されます (例では、a = 3)。

print ステートメントは {} にネストされているため、最後に宣言された変数 a のみが出力され、結果が得られます。

于 2012-12-22T03:58:05.317 に答える
1

ループ内で変数を宣言するときはいつでも、これは外部では使用できません (その変数の範囲外)。だからあなたのコードで

 void myproc()
{
    int a = 2;
    while (a == 2)
    {
        int a = 3;// This is not accessable to outside while loop. 
        printf("a = %d\t", a);
        break;
    }
    printf("a = %d\t", a);
}

3、3、1 を印刷したい場合は、while ループ内のintを削除してください :)

于 2012-12-22T04:09:11.217 に答える
1

実際、ループは非常に便利な難読化ツールです。

while ループのテストを考えてみましょう。このテストは、プログラムの実行中に 2 回実行されます。1 回目は、検査している a の値が 2 であるため、テストは成功します。2 回目の実行では、テスト中の a が a であるため、テストは失敗します。値 3 を保持する異なる a! これは非常に驚くべきことです。

私の同僚の説明によると、a の 3 つの宣言は、'{' と '}' で区切られたスコープ (または最初のスコープのワールド スコープ) にのみ存在します。これが文字通り真である場合、値 3 に割り当てられた宣言の内部は '{' と '}' によって完全に隠されているため、while (a == 2) テストは永久に合格するはずです。

int a = 1;         // world scope - a is 1
myproc() 
 {                 // New scope; can define names inside here
  int a = 2;       // Redefine a to be 2
  while ( a == 2 ) // We test whether a is 2
  {                // New scope; can define names inside here 
    int a = 3;     // Redefine a to be 3  
  }                // end of scope, the a = 3 disappears; also branch back to top of loop
 }                 // end of myprog scope, so the a=2 disappears

これを理解する方法は、while (test) { statements; }が実際に次のように実装されていることを理解することです。

if ( test ) {      // T1
   L1: {
      statements;
      if ( test )  // T2 
          goto L1;
   }
} 

実際には、テスト ステートメントが複製され、最初の 'T1' が '{' と '}' の外側のスコープで実行され、2 である a を取得して合格します。2 番目の 'T2' は '{' と '}' のスコープ内で実行され、3 である a を取得し、テストは失敗します。

あなたのステートメントを考えると、2 番目のテストは 3 である a のローカル スコープ定義を使用するため、ループは 1 回のパス後に終了します。

于 2012-12-22T05:05:06.593 に答える