2017-07-26 8 views
2

次の例では、関数func()は、ローカルポインタ変数〜main()のアドレスをに戻します。それはGCCでうまくいきます。ローカルポインタ変数のアドレスをmain()関数に戻す

だから、よく定義された動作ですか?

#include <stdio.h> 
#include <stdlib.h> 

int *func(void); 

int *func(void) 
{ 
    int *p; 
    p = malloc(sizeof *p); 
    *p = 10; 
    return p; 
} 

int main() 
{ 
    int *ptr = func(); 
    printf("%d\n",*ptr); 
    return 0; 
} 
+9

はいです。あなたはそれがそうではないと思わせるものは何ですか? "ポインタ変数のアドレス"ではなく "ポインタ変数の*値*"(もちろんアドレス)を返します。 –

+0

@FelixPalmenは、func()とmain()関数内で同じポインタのアドレスを出力します。http://ide.geeksforgeeks.org/sULNzy – rsp

+0

ポインタのアドレス**はありませんが、 *ポインタの値**。ポインタ**の**アドレスは 'func'の'&p'です。 'main'の'&ptr'です。もちろん、ポインタ**の**値**はアドレス**です(ポインタが指しているオブジェクトのアドレスです)。 –

答えて

2

pmalloc()によって割り当てられたメモリへのポインタです。成功した場合、このメモリ割り当ては明示的にfree dになるまで続きます。

pの値は、この場合はmain()という呼び出し関数に返されます。 pは成功した割り振りへのポインタであるか、ヌルポインタであり、戻り値(左辺値ではなく一時的)はptrに割り当てられます。だから、割り当てられたストレージはp自体の寿命は今func()が戻ってきたことを終了したものの、func()が返される前にpが保持する値のコピーである、ptrを介してアクセスすることができます。

もちろん、メモリリークを回避する必要がなくなったときは、ptrfreeです。 malloc()が失敗した場合、未定義の可能性があります。ptrはnullポインタです。

9

いいえ、あなたはローカル変数(アドレスの)へのポインタを返しません。

int i = 10; 
return &i; 

代わりに、ヒープに割り当てられたオブジェクトへのポインタを返します。

どこでもメモリがfreeではないので、メモリリークが発生しています。 freeを呼び出すには、のコードでを呼び出します(ただし、の値のポインターが返されない限り、関数の呼び出しチェーンは継続されます)。

+4

再実行するには、OPは**ローカル変数の**アドレスではなく、ポインタの**値**を返しています。 –

+1

完全性のために、OPの例で 'main()'(あるいは 'printf()'ステートメントの後に呼び出される他の関数)が 'free(ptr)'を呼び出す必要があることに言及したいかもしれません。 mallocされたメモリが 'func()'で解放されていれば、 'main()'の '* ptr'にアクセスすると未定義の動作になります。 – Peter

1

これは完全に有効です。

関数が返ってスタックフレームが縮小すると、スタックフレームの変数に何が起こるかは保証されません。

戻ってきたのは、mallocのメモリとのアドレスではなく、(スタックに割り当てられた)ローカル変数のアドレスです。これはstrdup()の動作と非常によく似ています。 hereから取られたstrdup()の実装がここにあります。 (「一部のプログラマの男」で述べたように)この

char * 
strdup(str) 
    const char *str; 
{ 
    size_t len; 
    char *copy; 

    len = strlen(str) + 1; 
    if (!(copy = malloc((u_int)len))) 
     return (NULL); 
    bcopy(str, copy, len); 
    return (copy); 
} 

1つの明らかな欠点はfree INGの責任が呼び出し元に渡されるということです。

1

これは有効で正しいコードですが、少し混乱します。

funcはint型のメモリを割り当てています。割り当ては、int型のポインタ変数の逆参照によって行われます。

メモリに整数値10が設定されています。 10は整数として設定する必要があります(コンパイラに依存する可能性があります)。しかし、間違いなく整数のサイズよりも大きくなることはないので、安全な操作でなければなりません。

その後、ポインタ値が関数によって返されます。

main()で返されるポインタは別の整数ポインタに設定されます。これは、malloc()によって割り当てられた元のメモリを指します。

その後、参照されていない整数ポインタがprintf()ステートメントに出力されます。これは10の値を出力します。

ここでは、free()呼び出しが欠けています。

これは、子供のための良い学問的練習になることができます。(malloc()がNULLポインタを返し、失敗する可能性があるため、または潜在的に割り当てられたメモリに、これはのためにチェックしなければならない)

func()内側
+1

"*割り当ては、int型のポインタ変数を逆参照することで行われます。*" no、 'sizeof'は式の* type *で動作します。デリファレンスはここでは起こりません。 –

関連する問題