2016-10-06 18 views
-1
int* getINT() 
{ 
    int y =10; 
    int *x = &y; 
    return x; 
} 
char* getARRAY() 
{ 
    char str[]= "Hai"; 
    return str; 
} 

int Main(void) 
{ 
    char *ptr; 
    int *result; 
    result = getINT(); 
    printf ("%d\n", *result); 
    ptr = getARRAY(); 
    printf("%s", ptr); 
} 

主関数* resultには、ptrにガベージ値がある間に10の値が保持されます。 * strがスコープを失うのに対し、* xがスコープを失わない理由は疑問です。戻り値の型ポインタがタイプの場合の関数の値

+0

はどちらも定義されていない動作なので、「作業中」機能に頼るべきではありません。 – mch

+0

偶然の問題。 –

答えて

1

両方とも無効で、resultはまだ10よりも偶然です。 関数内の値は、関数の現在のスタックフレーム内でスタックに割り当てられているため、関数内の値は、関数を終了するとすぐに存在します。関数が戻るとスタックフレームが削除され、別の関数を呼び出すとスペースが再利用されます。 したがって、関数のスタック上のデータへのポインタは、関数の外部では基本的に無意味です。チャンスがかなり高いため、アクセスしようとするとデータが上書きされるためです。

+0

ありがとう今私はそれを得た。実際には、私は10を得たときに私は混乱していた。今はそれがちょうど偶然であったことを理解する – SouthArcot

1

ローカル変数のアドレスを返すと、その変数は有効範囲外になり、その変数で使用されるメモリの場所は他の目的で再利用できます。このようなポインタの逆参照を試みると、undefined behaviorが呼び出されます。

未定義のビヘイビアを呼び出すと、何かが起こる可能性があります。コードがクラッシュしたり、予期しない結果が表示されたり、正しく動作するように見えることがあります。余分な未使用変数や追加/削除されたprintfの追加など、コードに一見無関係な変更を加えると、その動作が変更される可能性があります。 はおそらくは何が起こっているのかについては

は、あなたがメインでresultを移入時に、他の関数がまだ呼び出されていないので、getINTyが使用するスタック領域は、まだ上書きされていません。次のステートメントでは、そのポインタを逆参照してyの値を取得します。これは、関数が呼び出される前に実行されるため、yの値はまだ上書きされていないため、値を取得できます。

ptrの場合は、そのポインタを直接printfに渡します。 printfを呼び出した行は、スタックに書き込みを行い、以前にstrが占有していたメモリをgetARRAYに上書きします。

*resultを印刷する前にprintf("hello\n");を追加する場合は、その値として10を印刷しない可能性があります。同様に、ptrが指す文字列をループ内のローカル変数main(他の関数を呼び出さずに)にコピーした場合、おそらく文字列Haiが復元されます。

この場合も、この動作に依存することはできません。いくつかのコンパイラは、関数が復帰した後にスタック上にあったものをクリアすることを選ぶかもしれません。同様に、最適化レベルを変更すると、関数がインライン化され、スタックが変更されなくなる可能性があります。これはすべての未定義の動作の一部です。

関連する問題