C言語関係掲示板

過去ログ

No.512.malloc等による領域確保

[戻る] [ホームページ]
No.3976

malloc等による領域確保
投稿者---すすむ(2002/12/21 02:35:13)


malloc等による領域確保をした領域の使い方について教えて下さい。

ここに書き込みをされた内容でもありますが、reallocやmallocで
確保された領域を使う時ですが、例えば
char *area ;
area = malloc(128 * 3000) ;

この様に確保された領域には、strcpyとかでコピーができます。

char **area ;
char buf[128] ;
area = malloc(128 * 3000) ;
または、
area = realoc(128 * 3000) ;
for(i=0; .... i++) {
strncpy(area[i],buf,10)
area[i] = buf
}
としてもポインタ配列であるareaには入りません。
どうしてなのですか。
strdupを使うと代入できます。
どうしてなのですか。
前者と後者でどう違うのですか。


No.3977

Re:malloc等による領域確保
投稿者---silver fox(2002/12/21 03:42:25)


>strdupを使うと代入できます。
>どうしてなのですか。
>前者と後者でどう違うのですか。

 説明する前にサンプルを上げてみます。これでポインタの配列の構造が
分かるかなと思うのですが。取り敢えず見てみてください。

int main(int argc, char* argv[])
{
	char **area ;
	char *buf[] ={"abcde","fghij","klmno"};
    // ポインタテーブルを3個分確保したアドレスをセット
	area = (char **)malloc(sizeof(char*)*3);

	for(int i=0;i<3;i++) {
		// i 個番目のテーブルに6バイト確保したアドレスをセット
		area[i] = (char *)malloc(6);
		strcpy(area[i],buf[i]);  // おなじみの文字列コピー
		puts(area[i]);           // 表示
	}
	for(i=0;i<3;i++) {
		free(area[i]);	// i 個番目のポインタを開放
	}
	free(area);	// ポインタテーブルのポインタを開放
	return 0;
}


どうでしょう?

No.3978

Re:malloc等による領域確保
投稿者---silver fox(2002/12/21 03:58:38)


>malloc等による領域確保をした領域の使い方について教えて下さい。
>
>malloc等による領域確保をした領域の使い方について教えて下さい。

後はこちらの説明ですね。

 mallocはありませんがデータがセットされているバッファのアドレスを
セットしているのは同じ意味ですから。

 mallocはただサイズ分のメモリを確保し確保できた先のアドレスを返し
てきているだけです。そのアドレスをポインタにセットするのも、すでに
確保されているバッファのアドレスをセットするのも、ポインタの操作と
しては同じことです。ですから上記のリンクの説明でデータバッファを
mallocに置き換えて読めば分かるかなと思います。


No.3982

Re:malloc等による領域確保
投稿者---すすむ(2002/12/21 22:54:53)


silver foxさんありがとうございます。

ポインタの配列は、値がはいっているのではなく、値(実体)のある
場所を指し示すアドレスを格納しているのですね。

だから、ポインタ配列(*area[]、**area)に、値をコピーしたり、
配列の先頭アドレスを入れたりしても正しく値が格納されないので
すね。

添付して頂いたソースで、2回mallocを行っていますが、1回目の
mallocで、値(実体)格納する場所を指し示すアドレスを格納する
領域を確保し、ループ中で行っているmallocで、実際に値を格納
する領域を確保しているということですか。

実際、2回、mallocをやっていますが、1度に大きな領域を確保し
てはいけないのですか。
要は、ループ中で実行している分も含めて最初のmallocで確保する
ということはいけないのですか。

ちなみに、「char *」とは、4バイトと考えていいのですか。


No.3993

Re:malloc等による領域確保
投稿者---silver fox(2002/12/22 13:41:55)


>ポインタの配列は、値がはいっているのではなく、値(実体)のある
>場所を指し示すアドレスを格納しているのですね。

 そうです。ポインタとはそう言うものです。ちなみに今回で言うその値とはポ
インタですね。ただmallocの場合はまだ実体があるわけでは無く実体を入れる領
域を確保しただけです。

>添付して頂いたソースで、2回mallocを行っていますが、1回目の
>mallocで、値(実体)格納する場所を指し示すアドレスを格納する
>領域を確保し、ループ中で行っているmallocで、実際に値を格納
>する領域を確保しているということですか。

大体はそうですね。
ただ
1回目のmallocは実体(文字列)を格納する場所を指し示すアドレスを格納する
領域を確保してそのアドレスをarea変数にセットしています。そして
                            ^^^^^^^^^^^^^^^

2回目のmallocは実体を格納する領域を確保しそのアドレスを1回目のmallocで
確保したポインタ領域にセットしています。
         ^^^^^^^^^^^^^^^^^^^

アドレスを取得しているという事を忘れないでください。

>実際、2回、mallocをやっていますが、1度に大きな領域を確保し
>てはいけないのですか。
>要は、ループ中で実行している分も含めて最初のmallocで確保する
>ということはいけないのですか。

 いけないことはないですがそれでは何のためのポインタの配列か分からなくな
ってしまうのでは?一度に大きな領域を、ということは今回で言うと

[6バイトかける配列3個分18バイト]

を一度に確保するという事ですよね。それですと先頭のアドレスは分かりますが
2個目の文字列の先頭アドレスが文字列の長さから算出し直さなければならなく
なってしまいますよね。

>ちなみに、「char *」とは、4バイトと考えていいのですか。

 現行の32ビットCPUでは大体その様になっている様ですがこればかりは環境依
存によってどうなるかは分かりません。

No.3996

ありがとうございました。
投稿者---すすむ(2002/12/22 17:34:41)


silver foxさん、ありがとうございました。

わかりやすく説明していただき、理解できました。