7

チュートリアルでそれは言った

gotoステートメントを使用してブロックの途中にジャンプすると、そのブロック内の自動変数は初期化されません。

次に、以下のコードで、アクセス/宣言できる場合、なぜ初期化されないのですか?

int main()
{
   goto here;
   {
     int i=10;
     here:
      printf("%d\n",i);
   }
   return 0;
}

ps:outputはごみの値です。

4

6 に答える 6

12

i「アクセスできるのなら、なぜ...」という質問の背後に論理はありません。「アクセスi」できることは、何に対しても賛成でも反対でもありません。これは、printfステートメントがと同じスコープ内にあることを意味しiます。ただし、初期化子を飛び越えたため、変数は初期化されていません(チュートリアルで説明されているとおり)。

初期化されていない変数の読み取りは未定義の動作であるため、プログラムの形式が正しくありません。

変数は内部ブロック内に存在することがわかっているため、変数のメモリはiコンパイル時にすでに確保されています。ご想像のとおり、メモリは動的に割り当てられません。すでに存在しますが、が原因で決定的なものに設定されることはありませんgoto

経験則:初期化子を飛び越えないでください。

于 2012-07-12T08:18:58.437 に答える
3

変数は、{}そのスコープ内のステートメントの実行順序に関係なく、宣言されたスコープ(この場合はの間)に表示されます。のgoto初期化をバイパスします。つまり、が呼び出されiたときに値が未定義になります。printf()

于 2012-07-12T08:20:13.023 に答える
2

別の明白な状況を考えてみましょう。

int main()
{
    int i; //i is declared, but not initialized
    goto here;
    {
       i=10;//i is initialized 
       here: //you've skipped the initialization
       printf("%d\n",i);//and got garbage
    }
return 0;
}

あなたの場合:

int main()
{

    goto here;
    {
       //printf("%d\n",i);  // i does not exist here yet
       int i; //from here until the end of the scope variable i exists
       i=10;  // i exists here and smth is written into it
   here:  // i exists here
       printf("%d\n",i); // i exists here and it's value is accessed
    }
return 0;
}

だから、int i = 5;それは本当に2つのことです。1つは宣言であり、次gotoのようなものをスキップすることはできません(新しいスコープを開くことも影響を受けません。スコープの真ん中にジャンプしましたが、スコープはすでに存在していました)。goto2つ目は操作の割り当てであり、通常の操作(プログラムフロー)であるため、「中断」または「続行」または「戻る」によってスキップできます。

于 2012-07-12T08:42:57.343 に答える
0

Cコンパイラはソースファイルを解析し、変数の初期化を「記録」します。
届いたら

printf("%d\n", i)

変数iがすでに存在し、スコープ内にあるため、彼はそれを使用できるはずです。
実行時のスペースは、main関数の呼び出し直後、main()のコードが実行される前に、スタック上のi変数用に予約されています。

于 2012-07-12T08:20:59.093 に答える
0

言語標準がそう言っているので:

6.7.8初期化

セマンティクス

自動保存期間を持つオブジェクトが明示的に初期化されていない場合、その値は不確定です。

J.2未定義動作

次の状況では、動作は定義されていません。

自動保存期間のあるオブジェクトの値は、不確定なときに使用されます。

6.8.4.2switchステートメント

例人工プログラムフラグメント

switch (expr)
{
  int i = 4;
  f(i);
  case 0:
    i = 17;
    /* falls through into default code */
  default:
    printf("%d\n", i);
}

識別子がiのオブジェクトは、自動保存期間(ブロック内)で存在しますが、初期化されることはありません。したがって、制御式の値がゼロ以外の場合、printf関数の呼び出しは不確定な値にアクセスします。同様に、関数fの呼び出しには到達できません。

于 2012-07-12T08:43:40.730 に答える
-1

Cを使用すると、実際に初期化されているかどうかに関係なく、アドレス空間内のあらゆるものにアクセスできます。そのように動作すると、クラッシュしたり、ゴミが表示されたり、便利なものが印刷されたりすることがありますが、それはすべて未定義の動作です。便利なトリックですが、プログラムを破るのに最適な方法です。結果を得るだけでトリックが機能するとは思わないでください。

于 2012-07-12T08:20:21.180 に答える