1

次のコードでは

label:
int a;
goto label;

新しい変数を作成するか、同じ変数を使用しますか
また、goto を使用して関数を何度も呼び出すとどうなりますか

4

3 に答える 3

2

まず第一に、ラベルの後に statement が続く必要があり、宣言はステートメントではないため、これはビルドされません。

6.8.1 ラベル付きステートメント

構文

1 ラベル付きステートメント:
        識別子 : ステートメント
        ケース 定数式 : ステートメント
        デフォルト : ステートメント

第二に、これは新しい変数を作成する べきではありません。goto新しいスコープを導入しないため、a各反復の新しいインスタンスを作成しません。また、次のような新しいスコープを導入している状況でも

for (;;) {int a; ... }

のスペースaは (通常) 1 回だけ割り当てられます。論理的aにはループの反復ごとに新しいインスタンスを扱っていますが、物理的には (通常は) 同じメモリ位置をリサイクルしています。a 以前のスペースを再利用せずに新しいスペースを物理的に作成したコンパイラは、IMO がひどく壊れてしまいます。

くすくす笑うために、私は次のように書きました:

#include <stdio.h>

#ifdef __STDC_VERSION__
  #if __STDC_VERSION__ >= 199901L
    #define C99
  #endif
#endif

int main(void)
{
label:
  #ifdef C99
    ;
  #endif
  int a;
  printf("&a = %p\n", (void *) &a); 
  goto label;

  return 0; 
}

でビルドするとgcc -std=c99 -pedantic -Wall -Werror、次の出力が得られます。

&a = 0xbf98ad8c
&a = 0xbf98ad8c
&a = 0xbf98ad8c
&a = 0xbf98ad8c
&a = 0xbf98ad8c
&a = 0xbf98ad8c
&a = 0xbf98ad8c
&a = 0xbf98ad8c
&a = 0xbf98ad8c
&a = 0xbf98ad8c
&a = 0xbf98ad8c
&a = 0xbf98ad8c
&a = 0xbf98ad8c
&a = 0xbf98ad8c
于 2012-06-07T11:53:12.973 に答える
1

いいえ、その変数を再度宣言してメモリを割り当てることはありません。同じ変数を使用します。

さらに、プログラムが間違っています。ラベルを宣言の前に置くことはできません。ラベルはステートメントの前に置く必要があり、宣言はステートメントではありません。修正するには、ラベルの後にセミコロンを付けます。

于 2012-06-07T10:56:04.430 に答える
1

この質問は、「コンパイラはローカル変数をいつ、どのように割り当てるのですか?」という質問であった可能性もあります。

次のようなコードがあるとしましょう。

{
  lots_of_code();

  int x;

  lots_of_code();

  x = 5 + something;

  lots_of_code_not_using_x();

  return x;
}

このコードはローカル スコープにあります。この場合、関数の内部のように見えますが、同じ規則が if ステートメントや for ループなどの内部に適用されます。このコードに遭遇すると、コンパイラはいくつかの質問をします。

  • x をまったく割り当てる必要がありますか、それとも最適化して取り除くことができますか? いいえ、この場合、コードの意味を変更せずに x を最適化することはできません。
  • x を割り当てるのに最適な場所はどこですか? これは完全に CPU 固有です。x は、スタックまたは CPU レジスタなどに割り当てることができます。
  • x を割り当てるのはいつですか? これに対する答えは常に「初めて使用するとき」です。この場合、行x = 5 + something;が実行される前に x が確実に割り当てられることはありません。その場合でも、必ずしも割り当てられるとは限りません。コンパイラーは、lots_of_code_not_using_x();より効率的でコードの意味を変更しない場合は、最初に実行することを選択して、命令の順序を変更することもできます。その場合、コードが return ステートメントに達したときに x が割り当てられます。

x は、スコープに入る時点からスコープの終わりまで有効であることが標準によって保証されています。9899:2011 6.2.4

「5 識別子がリンケージなしで宣言され、ストレージクラス指定子 static なしで宣言されているオブジェクトは、一部の複合リテラルと同様に、自動ストレージ期間を持ちます...」 /--/

"6 可変長配列型を持たないオブジェクトの場合、 その有効期間は、関連付けられているブロックへのエントリから、そのブロックの実行が何らかの方法で終了するまで延長されます。終了しません, 現在のブロックの実行.) ブロックが再帰的に入る場合, オブジェクトの新しいインスタンスが毎回作成されます. オブジェクトの初期値は不定です. オブジェクトに初期化が指定されている場合, それはブロックの実行で宣言または複合リテラルに到達するたびに実行されます。それ以外の場合、宣言に到達するたびに値が不確定になります。」

したがって、質問に答えるには: いいえ、goto スパゲッティは、変数の割り当て方法にまったく影響しません。たとえば、変数を使用するコードがあったint a = 0;場合、コンパイラが goto 混乱全体を最適化する能力に応じて、そのコードが何度も実行される可能性があります。

于 2012-06-07T11:42:01.887 に答える