c言語のmalloc関数は確保するメモリの領域を、配列としてのみしか処理出来ないのですか。
つまり、malloc関数で確保したメモリの領域を変数、また多次元配列、また構造体としては処理出来ないのでしょうか。
c言語のrealloc関数は以前の確保したメモリの領域から、確保し直したメモリの領域の場所が変わるかもしれないという事ですが、この場合の場所が変わるという意味は、メモリの領域のアドレスが変わるという事でしょうか。
また、以前の確保したメモリの領域に代入していたデータが使用出来なくなるという事でしょうか。
A 回答 (8件)
- 最新から表示
- 回答順に表示
No.1
- 回答日時:
mallocやreallocは指定サイズのメモリを確保するだけなので、そこを配列として使うかどうかにはプログラムの問題です。
mallocやreallocはどう使われるかには一切関知しません。
reallocではデータはある程度保証されます。
参考URL:http://www9.plala.or.jp/sgwr-t/lib/realloc.html
この回答への補足
realloc関数の戻り値がNULLの場合は、もしかして必要なメモリのサイズの不足だけでなく、元のメモリの領域に代入したデータをコピー出来なかった場合も含まれる気がしますがどうなんでしょうか。
realloc関数などのメモリ関係の関数では戻り値を型キャストしますが、戻り値をポインタに代入すれば宣言したポインタに型が有るので型キャストしなくてもよさそうな気がしますがどうなんでしょうか。
No.2
- 回答日時:
>malloc関数で確保したメモリの領域を変数
mallocの引数を、例えばsizeof(int)とでも書いてやれば、int型のアドレスが返ってきます。
そのアドレスが指している領域は、あたかもint型の変数であるかのように扱えます。
>また多次元配列
いわゆる多次元配列っていうのは要するに配列の配列(の配列...、以下同様)ってことですので、
配列(らしきものとして)扱えることがおわかりでしたら、その考えを拡張すればよいだけです。
>また構造体
mallocの引数に、扱いたい構造体の大きさを指定すればよいだけのことです。
>この場合の場所が変わるという意味は、メモリの領域のアドレスが変わる
そのとおりです。
>以前の確保したメモリの領域に代入していたデータが使用出来なくなる
おそらくはそういうことでしょうね。
reallocの結果、場所が変わった場合は、以前にmallocで確保してあった領域は
誰が使ってもいい状態になってしまってます。
不用意にアクセスしない方が無難でありましょう。
この回答への補足
なるほど、malloc関数でメモリの領域を変数として確保するには、配列において配列の要素を1つとしてメモリを確保すれば良いのですね。
すみませんが、malloc関数でメモリの領域を多次元配列、また構造体として確保する方法について詳しく教えて頂けるとありがたいです。
それと、realloc関数は以前確保したメモリの領域に代入したデータが使用出来なくなるという事ですが、realloc関数は、どのように使用するのですか。
No.3
- 回答日時:
>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で割り当てられた領域のサイズを変更する時に使います。
No.4
- 回答日時:
現在の規格では、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);
は、多次元配列のように各要素にアクセスできるが、多次元配列じゃない。
No.6
- 回答日時:
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 だけで作ることができます.
この回答への補足
なるほど、realloc関数で、もしも確保するメモリの領域のアドレスが変わる場合において、確保するメモリの領域を拡大する場合は、確実に元のメモリの領域の全てのデータをコピー出来るという事ですね。
また、確保するメモリの領域を縮小する場合は、プログラマがmalloc関数などで新しいメモリの領域を確保して、memcpy関数で元のメモリの領域の必要なデータを新しいメモリの領域にコピーして、free関数で元のメモリの領域を解放しなければ、元のメモリの領域の必要なデータが使用出来る保証は無いという事ですね。
No.7
- 回答日時:
できます。
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内で前のデータは自動的にコピーされます。
(そうでないと使い道が無いので)
No.8
- 回答日時:
#6 の「補足」中「また」以下の文章は意味不明.
realloc ではメモリ領域が移動するかどうかにかかわらず「意味のある部分」, つまり「元の大きさと新しい大きさのうち小さい方の分」については元のデータが保存されます. ということで, realloc で元よりも小さな領域を確保する場合, 「何もしない」実装もありえます. ただし, #6 で書いたようにそのような動作が保障されているということでもありません.
詳しくは規格を読んでください.
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語の質問です。 以下の命令を実行するプログラムを作りました ①文字列aとbの長さを表示 ②aとb 1 2022/04/29 15:35
- C言語・C++・C# ポインタの型変換、どうやるんでしたっけ? 2 2022/03/28 11:00
- C言語・C++・C# スタックフレームの消滅 6 2023/05/20 12:33
- C言語・C++・C# あまりわかりません。 複素数$c$を具体的に定めた複素写像写像$f_c(z)$に対して、原点を含む領 4 2022/10/25 09:17
- その他(学校・勉強) この中で間違ってある説明はありますか?詳しい方に教えていただきたいです。 A. 1つのプログラムが複 2 2023/07/14 01:15
- C言語・C++・C# 写真のc言語の問題がa以外わかりません。 正直aも自信がなく、解説していただけないでしょうか? 答え 3 2022/04/29 18:21
- CPU・メモリ・マザーボード ストリーミングの一時処理用の領域について 1 2023/04/11 21:55
- ノートパソコン パソコンを、アップグレードした後に出来た、Cドライブの後に出来た、このドライブは? 3 2023/04/03 17:10
- C言語・C++・C# sprintf()の使い方について 1 2022/08/17 16:16
- 数学 絵は 1 2022/10/25 15:56
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
allocってなんですか?
-
newしないオブジェクトについて
-
配列の添え字の最大数とは?
-
void*型のデータサイズ
-
CでOpenMP、パラレル内での共有...
-
スタック破壊の上手な見つけ方...
-
グローバル変数のサイズ
-
new、memset()、エラー
-
UNIX socket TCP 受信バッファ...
-
指定したメモリアドレスの値の...
-
128ビット変数の符合表現について
-
x64環境で連続4GB以上のメモリ...
-
DLLのマルチスレッドの動作につ...
-
LPWSTRのコピー
-
メモリ解放について
-
配列の中身のdelete
-
メモリをたくさん使うテストプ...
-
アセンブラでのメモリの動的確...
-
malloc呼び出し時のセグメンテ...
-
構造体でchar name[]と*nameの...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
mallocについて
-
c言語のポインタへの文字列入力...
-
allocってなんですか?
-
newしないオブジェクトについて
-
ヒープメモリの解放について
-
C++で、メンバもヒープに確保さ...
-
MSDNがgethostbynameではなくge...
-
プログラムが途中で強制終了し...
-
配列の添え字の最大数とは?
-
Accessで、メモリを開放するタ...
-
malloc呼び出し時のセグメンテ...
-
ヒープ領域の限界値設定
-
スタック破壊の上手な見つけ方...
-
C言語 mallocとfreeについて
-
指定したメモリアドレスの値の...
-
stringの最大サイズ
-
16進ダンプのプログラム
-
入れ子になった構造体について
-
64ビットと32ビットの違い
-
free関数で動作が止まる
おすすめ情報