- 締切済み
c言語のmalloc関数、またrealloc関数
c言語のmalloc関数は確保するメモリの領域を、配列としてのみしか処理出来ないのですか。 つまり、malloc関数で確保したメモリの領域を変数、また多次元配列、また構造体としては処理出来ないのでしょうか。 c言語のrealloc関数は以前の確保したメモリの領域から、確保し直したメモリの領域の場所が変わるかもしれないという事ですが、この場合の場所が変わるという意味は、メモリの領域のアドレスが変わるという事でしょうか。 また、以前の確保したメモリの領域に代入していたデータが使用出来なくなるという事でしょうか。
- みんなの回答 (8)
- 専門家の回答
みんなの回答
- Tacosan
- ベストアンサー率23% (3656/15482)
#6 の「補足」中「また」以下の文章は意味不明. realloc ではメモリ領域が移動するかどうかにかかわらず「意味のある部分」, つまり「元の大きさと新しい大きさのうち小さい方の分」については元のデータが保存されます. ということで, realloc で元よりも小さな領域を確保する場合, 「何もしない」実装もありえます. ただし, #6 で書いたようにそのような動作が保障されているということでもありません. 詳しくは規格を読んでください.
- higeG
- ベストアンサー率22% (4/18)
できます。 struct hoge *ptr = malloc(sizeof(struct hoge)); ptr->member = 0; や int (*ary)[4] = malloc(sizeof(int)*3*4); for (i=0; i<3; i++) { for (j=0; j<4; j++) { (*ary)[i][j] = i*j; } } 等とできたはずです。 実際にコンパイルしていないので間違っていたらごめんなさい。 また、reallocで確保領域が移動した場合は、realloc内で前のデータは自動的にコピーされます。 (そうでないと使い道が無いので)
- Tacosan
- ベストアンサー率23% (3656/15482)
realloc は大雑把に 1. malloc する 2. malloc が成功した (つまり必要な分のメモリが確保できた) ら古いところから memcpy して古いアドレスを free 3. 1 の返り値を返す という動作をしすると思って構いません (領域を小さくするときには malloc しないかもしれないが, 「malloc しないこと」は保証されていない). malloc (か何か) で新たに確保した場合, 古いところは free されるのでそのアドレス自体は使えません. ただ, 内容は memcpy で (かどうかは知らんがとにかく) 新しいところにコピーしてくれるので, 「意味のある部分」は新しいアドレスを使ってアクセスできます. NULL を渡すと malloc と等価な動作をするので, 大きさが可変なバッファを char *buffer = NULL; // 省略 char *p = realloc(buffer, new_size); if (p) { buffer = p; // なんかする } else { // メモリが足らん } のように realloc だけで作ることができます.
- yaemon_2006
- ベストアンサー率22% (50/220)
>多次元配列のように各要素にアクセスできるが 多次元配列と同じようにa[i][j]で各要素にアクセスできるが
- yaemon_2006
- ベストアンサー率22% (50/220)
現在の規格では、malloc、realloc等はvoid *を返すので明示的なキャストは不要。 多次元配列をmallocで確保するには、 例えば、 int (*a)[5]; a = malloc(sizeof(int) * 5 * 5); でa[0][0]~a[4][4]を使える。 ちなみに、 int **a, i; a = malloc(sizeof(int *) * 5); for(i = 0; i < 5; ++ i) a[i] = malloc(sizeof(int) * 5); は、多次元配列のように各要素にアクセスできるが、多次元配列じゃない。
- notnot
- ベストアンサー率47% (4900/10358)
>realloc関数の戻り値がNULLの場合は、もしかして必要なメモリのサイズの不足だけでなく、元のメモリの領域に代入したデータをコピー出来なかった場合も含まれる気がしますがどうなんでしょうか。 reallocを正しく使っている限り、コピー出来ないのはあり得ません。 >realloc関数などのメモリ関係の関数では戻り値を型キャストしますが、戻り値をポインタに代入すれば宣言したポインタに型が有るので型キャストしなくてもよさそうな気がしますがどうなんでしょうか。 代入するとコンパイルで「型が違う」と警告が出ますが、それを気にしないのであれば、キャストは不要です。 >malloc関数でメモリの領域を多次元配列、また構造体として確保する方法 確保する方法は何に使うにせよ同じです。確保するサイズを指定して、使いたい物を指すポインタ変数に返値を代入するだけ。 Tが構造体のtypedefされた型だとして、 T *p; p = (T *)malloc(sizeof(T)); 多次元配列は、配列の配列なので面倒です。2x3のint型配列だとすると、 int **p; p = (int**)malloc(sizeof(int*)*2); p[0] = (int*)malloc(sizeof(int)*3); p[1] = (int*)malloc(sizeof(int)*3); これで、p[0][0], p[0][1], p[0][2], p[1][0], p[1][1], p[1][2] が使えます。 >realloc関数は、どのように使用するのですか。 mallocで割り当てられた領域のサイズを変更する時に使います。
- asuncion
- ベストアンサー率33% (2127/6289)
>malloc関数で確保したメモリの領域を変数 mallocの引数を、例えばsizeof(int)とでも書いてやれば、int型のアドレスが返ってきます。 そのアドレスが指している領域は、あたかもint型の変数であるかのように扱えます。 >また多次元配列 いわゆる多次元配列っていうのは要するに配列の配列(の配列...、以下同様)ってことですので、 配列(らしきものとして)扱えることがおわかりでしたら、その考えを拡張すればよいだけです。 >また構造体 mallocの引数に、扱いたい構造体の大きさを指定すればよいだけのことです。 >この場合の場所が変わるという意味は、メモリの領域のアドレスが変わる そのとおりです。 >以前の確保したメモリの領域に代入していたデータが使用出来なくなる おそらくはそういうことでしょうね。 reallocの結果、場所が変わった場合は、以前にmallocで確保してあった領域は 誰が使ってもいい状態になってしまってます。 不用意にアクセスしない方が無難でありましょう。
補足
なるほど、malloc関数でメモリの領域を変数として確保するには、配列において配列の要素を1つとしてメモリを確保すれば良いのですね。 すみませんが、malloc関数でメモリの領域を多次元配列、また構造体として確保する方法について詳しく教えて頂けるとありがたいです。 それと、realloc関数は以前確保したメモリの領域に代入したデータが使用出来なくなるという事ですが、realloc関数は、どのように使用するのですか。
- SaKaKashi
- ベストアンサー率24% (755/3136)
mallocやreallocは指定サイズのメモリを確保するだけなので、そこを配列として使うかどうかにはプログラムの問題です。 mallocやreallocはどう使われるかには一切関知しません。 reallocではデータはある程度保証されます。
補足
realloc関数の戻り値がNULLの場合は、もしかして必要なメモリのサイズの不足だけでなく、元のメモリの領域に代入したデータをコピー出来なかった場合も含まれる気がしますがどうなんでしょうか。 realloc関数などのメモリ関係の関数では戻り値を型キャストしますが、戻り値をポインタに代入すれば宣言したポインタに型が有るので型キャストしなくてもよさそうな気がしますがどうなんでしょうか。
補足
なるほど、realloc関数で、もしも確保するメモリの領域のアドレスが変わる場合において、確保するメモリの領域を拡大する場合は、確実に元のメモリの領域の全てのデータをコピー出来るという事ですね。 また、確保するメモリの領域を縮小する場合は、プログラマがmalloc関数などで新しいメモリの領域を確保して、memcpy関数で元のメモリの領域の必要なデータを新しいメモリの領域にコピーして、free関数で元のメモリの領域を解放しなければ、元のメモリの領域の必要なデータが使用出来る保証は無いという事ですね。