2011-09-14 7 views
1

なぜこのコードが予期せぬ出力を出すのですか?Cでアドレスを返す

int * func(int *xp) 
{ 
    int y = 10 + *xp; 
    return (&y); 
} 
void main() 
{ 
    int x = 10; 
    int *xp = func(&x); 
    printf("%d\n", x); 
    printf("%d\n", *xp); 
} 

予想される出力:

10 
20 

実出力:

10 
1074194112 
+4

'void main' ** ARRRRRRRRGGGGGGGGHHHHHHH!** – pmg

+0

よくある質問の種類。 [Eric Lippertの説明](http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope/6445794#6445794)を参照してください。 1851 upvotes and counting ... – eran

+1

@pmg void mainの問題は何ですか?コンパイラがそれに対してエラーを出さないとき、なぜあなたは気になるのですか? –

答えて

11

あなたがスコープ外にあなたがfuncを離れる瞬間を行く変数(y)へのポインタを返すされています。これは未定義の動作です。

は、それはあなたが達成しようとしているものを完全に明らかではないが、この問題を解決するにはいくつかの方法があります。

  1. 返り値でint
  2. *xpを変更して何も返さない。
  3. さらにint*パラメータをとり、その結果をそこに格納します(voidを再度返します)。
  4. mallocまたはnewを使用してヒープ上にメモリを割り当て、それを返します(呼び出し元はメモリを正しく解放する責任があります)。

上記のうちどれがあなたの問題に適用できるのかは、より広い文脈を知らないと言うことはできません。

最後に、main() should return int(これを検出するための@pmg)。これはあなたが持っている問題を指摘する価値があります。

+0

候補者をインタビューするために、このバリエーションをお尋ねします。 – user47559

2

関数が返ってきたときに、yが範囲外になるためです。 yがスタックに宣言されたことを忘れないでください。これは未定義の動作です。

1

ローカル変数のアドレスを返してからそれをデコンバイジングすると、は未定義の動作になります。

コールは、funcが使用するのと同じメモリ(スタック)領域を使用するため、funcのスタックフレームを独自の内部変数と関数引数で上書きします。

int* func (int *xp) { 
    int* res = malloc(sizeof(int)); 
    if (!res) { 
    perror('Cannot allocate memory in func'); 
    exit(1); 
    } 
    *res = 10 + *xp; 
    return res; 
} 

freeにそれを忘れないでください:

int main(void) { 
    int x = 10; 
    int *xp = func(&x); 
    printf("%d\n", x); 
    printf("%d\n", *xp); 
    free(xp); 
    return 0; 
} 
+0

ポータブル 'main'は' int'を返すべきです。私はあなたの答えを変えました。 – pmg

+0

@pmgありがとう、最初にそれを含めるべきだった。 – phihag

2

< real_life_example>

あなたを想像しmallocヒープにメモリを割り当て、この問題を解決するための

テーブルにリンゴを置く。あなたはそれを紙の上に書き留めます。 その後、誰かが来てリンゴをとります。紙の上の位置は今や意味をなさない。

</real_life_example>

+2

...あなたは誰かが同じ場所でテーブルに置くバナナをつかむかもしれません。 – phihag

+0

彼は彼です...私はあなたのコメントが好きです。 –

+1

「バナナ」を「りんごの刃でいっぱいのリンゴ」に置き換えると、あなたのコードではどうなるのでしょうか?:-) –

1

func次のようになります。誰もがすでに述べたように、あなたは一時変数のアドレスを返すようにしようとしている

// C++ 
int* func(int* xp) 
{ 
    int* y = new int; 
    *y = 10 + *xp; 
    return y; 
} 
0

。誰も言及していないものが最も簡単な解決策です。関数内で静的変数をキャストします。これにより、プログラム全体のメモリに残ります。

int * func(int *xp) 
{ 
    static int y; 
    y = 10 + *xp; 
    return (&y); 
} 
void main() 
{ 
    int x = 10; 
    int *xp = func(&x); 
    printf("%d\n", x); 
    printf("%d\n", *xp); 
} 

予想通り、この作品。もちろんこれについてはより良い方法がありますが、関数のスコープ内で変数を宣言し、そのアドレスを返す場合は、これが最も簡単な解決方法です。この関数が呼び出されるたびに、それはyを変更します。それはあなたにコピーを与えません。

関連する問題