2016-09-07 6 views
4

次のコードを考慮してください。C-関数がローカル変数へのポインタを返す

#include<stdio.h> 
int *abc(); // this function returns a pointer of type int 

int main() 
{ 
    int *ptr; 
    ptr = abc(); 
    printf("%d", *ptr); 
    return 0; 
} 

int *abc() 
{ 
    int i = 45500, *p; 
    p = &i; 
    return p; 
} 

出力:

私はlinkに係る行動のこのタイプが定義されていません知っています。しかし、なぜ私はプログラムを実行するたびに正しい値を得ているのですか?

+0

未定義の動作が許可されているためです。ところで、私はこの質問に間違ったことは何も見ません。 Upvoted。 – Bathsheba

+3

あなたのプログラムはとてもシンプルだからです。 'abc()'と 'printf()'の呼び出しの間に他の関数への呼び出しを挿入してみてください – Serge

+3

だから何ですか? "不定"とは "ランダム"を意味するものではありません... –

答えて

3

abcを呼び出すたびに、スタックの一番上にある領域がすべてのローカル変数を書き込む場所として「マーク」されます。これは、スタックの先頭がどこであるかを示すポインタを動かすことによって行われます。その領域はスタックフレームと呼ばれます。関数が復帰すると、スタックポインタを元の位置に移動することで、その領域をもう使用したくないことを示します。その結果、後で他の関数を呼び出すと、スタックのその領域を独自の目的のために再利用します。しかし、あなたの場合、他の機能はまだ呼び出されていません。スタックの領域が同じ状態になるようにします。

上記のすべては、コードの動作を説明しています。すべてのCコンパイラがそのように関数を実装する必要はないので、その動作に頼るべきではありません

+5

これは*非常に実装固有のものです。 –

+0

はい、私は彼の好奇心を満たすために行動を説明しています。 – redneb

+0

例として、i8051のKeil Cコンパイラ:リンク時に呼び出しツリーを構築してデータセグメントにローカルを割り当てます。スタックはコントロールを渡すためにのみ使用されます。 – Serge

2

まあ、未定義の振る舞いは未定義です。 UBのまたはUBを呼び出すプログラムの出力)を決して使用することはできません。

たぶん、は、もしかしたらご使用の環境でとあなたコードのために、ローカル変数に割り当てられたメモリの場所がないはまだアクセスをOSによってを再利用しているが、それは持っているという保証はありません他のプラットフォームと同じ動作です。

+0

UBとは何ですか? plsは – Cody

+1

@Cody UB - >未定義の動作を定義します。 –

関連する問題