【掲示板ご利用上の注意】

 ※題名は具体的に!
 ※学校の課題の丸投げ禁止!
 ※ソースの添付は「HTML変換ツール」で字下げ!
 ※返信の引用は最小限に!
 ※環境(OSとコンパイラ)や症状は具体的に詳しく!
 ※返信付き投稿の削除は禁止!
 ※マルチポスト(多重投稿)は慎んで!

 詳しくはこちら


本当はこんなに大きく書きたくはないのですが、なかなか守っていただけなくて…。
 守ってくださいね。お願いします。(by管理人)

C言語ソース⇒HTML形式ツール掲示板2こちら


管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.23249

malloc()関数による文字列配列の動的確保
投稿者---zero(2005/09/23 18:46:33)


malloc()関数により文字列配列の為の領域を動的に確保する場合(事前には、幾つの文字列を格納するのかは、分っていないものとする)、以下のソースのような感じになると思うのですが、自信がないため、間違っている個所があればご指摘下さい。
(処理内容を明確にするためエラー処理は省いてあります)

#include <stdlib.h>

int main(int argc, char *argv[]) {
    char **list; /* 文字列配列を指すポインタ */

    ---- 処理の流れで4つの文字列を格納する領域が必要になった ----

    list = malloc(sizeof( (char *) * 4)));
    
    /* それぞれの文字列配列の領域として10文字分確保 */
    list[0] = malloc(10);
        -----
    list[3] = malloc(10);

    list[0] = "hello";
        -----
    list[3] = "world";

    exit(0);
}   



よろしくお願いします。


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:malloc()関数による文字列配列の動的確保 23250 Blue 2005/09/23 18:54:35
<子記事> Re:malloc()関数による文字列配列の動的確保 23258 RiSK 2005/09/23 23:01:12
<子記事> Re:malloc()関数による文字列配列の動的確保 23268 まきじ 2005/09/24 00:02:35


No.23250

Re:malloc()関数による文字列配列の動的確保
投稿者---Blue(2005/09/23 18:54:35)


>    list[0] = "hello";
>        -----
>    list[3] = "world";
折角確保したのに使わないのでしょうか?
(freeする場合、出来なくなっちゃうかと)

strcpy( list[ 0 ], "hello" );
----
strcpy( list[ 3 ], "world" );



この投稿にコメントする

削除パスワード

No.23251

Re:malloc()関数による文字列配列の動的確保
投稿者---zero(2005/09/23 19:00:52)


>strcpy( list[ 0 ], "hello" );
----
>strcpy( list[ 3 ], "world" );<

早速の返信ありがとうございます。
大きな勘違いをしていました。

そうですね。"hello"という文字列のために、自分で領域をmalloc()で確保してやる必要は
ないんですね。お恥しい。


この投稿にコメントする

削除パスワード

No.23252

Re:mallocの返り値について
投稿者---zero(2005/09/23 19:23:58)


ふと思ったのですが、malloc()は引数で指定された大きさのサイズの領域をメモリに確保し、
その先頭アドレスを返り値として返しますが、プロトタイプではその返り値の型はvoid型の
ポインタとなっています。
それなのに変数listは char **list とポインタのポインタで宣言していますが、mallocの
戻り値の左辺にしてもよいのでしょうか?意味的には問題ないように思いますが。

ご教授よろしくお願いします。


この投稿にコメントする

削除パスワード

No.23253

Re:mallocの返り値について
投稿者---m(2005/09/23 20:19:02)


> mallocの戻り値の左辺にしてもよいのでしょうか?

無論,問題ありませんとも。
……と言いたいところですが,キャストが欲しいところです。
↓は,プログラムへの引数を list に格納して表示するコードです。

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

int main(int argc, char *argv[]) {
    int i = 0;
    char **list = NULL;

    /* listにメモリを割り当て,文字列を入れる */
    list = (char **)malloc(sizeof(char *) * argc);
    for (i=0; i<argc; ++i) {
        list[i] = (char *)malloc(strlen(argv[i]) + 1);
        strcpy(list[i], argv[i]);
    }

    /* list の中身を表示 */
    for (i=0; i<argc; ++i) {
        printf("list[%d]=%s\n", i, list[i]);
    }

    /* メモリを解放 */
    for (i=0; i<argc; ++i) {
        free(list[i]);
    }
    free(list);

    /* bye :-) */
    return 0;
}



この投稿にコメントする

削除パスワード

No.23254

Re:mallocの返り値について
投稿者---zero(2005/09/23 20:43:12)


返信ありがとうございます。

>……と言いたいところですが,キャストが欲しいところです。
その理由は何でしょうか?昔はmallocの戻り値を左辺値の型に明示的にキャストしてやる必要がありましたが、現在は特にキャストは必要ないはずですが、このlist変数のようにポインタのポインタの場合はキャストしておいた方がよいという事でしょうか?
また、argv[0]〜argv[n]の場合はプロセス空間のメモリにこの文字列のメモリ領域が既に確保されているわけではない(?)ので
list[i] = malloc(strlen(argv[i])+1);
のように新に領域を確保してやる必要があるのでしょうか?(先のBlueさんとのやり取りとの違い).

またfree()関数の引数もvoid型のポインタなのでmさんのおっしゃる通りならfree()もfree((char *)list))としてやる方がいいのでしょうか?


この投稿にコメントする

削除パスワード

No.23255

Re:mallocの返り値について
投稿者---まきじ(2005/09/23 20:53:34)


> またfree()関数の引数もvoid型のポインタなのでmさんのおっしゃる通りならfree()もfree((char *)list))としてやる方がいいのでしょうか?

C言語では、キャストも解放も遣らなくても問題ありません。

キャストについては、X3010 7.20.3 に記載されています。
http://www.st.rim.or.jp/~phinloda/cqa/cqa16.html こことか。

大量に malloc() してる場合は、free() が必要になるでしょうが、
プログラムの終了時に解放されるので、malloc() が少なければ
free() で解放しなくて問題ありません。


この投稿にコメントする

削除パスワード

No.23258

Re:malloc()関数による文字列配列の動的確保
投稿者---RiSK(2005/09/23 23:01:12)


>間違っている個所があればご指摘下さい。
    list = malloc(sizeof( (char *) * 4)));
これでは,おそらくsizeof(int)しか確保されません。

欲しいのは,(char*のサイズ)×4では無いですか?


この投稿にコメントする

削除パスワード

No.23259

Re:malloc()関数による文字列配列の動的確保
投稿者---zero(2005/09/23 23:05:54)


>欲しいのは,(char*のサイズ)×4では無いですか?

printf("%d\n", sizeof(char *)*4);;

これで"16"と表示されたので問題ないと思いますが。


この投稿にコメントする

削除パスワード

No.23261

Re:malloc()関数による文字列配列の動的確保
投稿者---あかま(2005/09/23 23:17:05)


最初に投稿されたプログラムのほうが
sizeof(char *)*4
ではなく
sizeof( (char *) * 4)
になってますよ。

これってコンパイラの解釈はどうなるんだろう?
4をアドレスと解釈して参照して、参照先の値を(char*)にキャストして、そのサイズを見てる?
つまり(char*)のサイズで4。
と思ったらコンパイルエラー「無効な間接参照」

sizeof( (char *) * (char**)4)
ならうまくいって4でした。って全然関係ないですね。


この投稿にコメントする

削除パスワード

No.23264

Re:malloc()関数による文字列配列の動的確保
投稿者---zero(2005/09/23 23:23:25)


>最初に投稿されたプログラムのほうが
>sizeof(char *)*4
>ではなく
>sizeof( (char *) * 4)
>になってますよ。

本当ですネ。すいません。"sizeof(char *) * 4"の間違いです。


この投稿にコメントする

削除パスワード

No.23267

Re:malloc()関数による文字列配列の動的確保
投稿者---RiSK(2005/09/23 23:58:36)


>RiSK
>これでは,おそらくsizeof(int)しか確保されません。

は間違いで

>あかまさん
>と思ったらコンパイルエラー「無効な間接参照」

が正しいです。失礼しました。


この投稿にコメントする

削除パスワード

No.23260

Re:malloc()関数による文字列配列の動的確保
投稿者---あかま(2005/09/23 23:08:11)


>欲しいのは,(char*のサイズ)×4では無いですか?
2次元配列っぽいので、sizeof(char**)×4かな?


この投稿にコメントする

削除パスワード

No.23263

Re:malloc()関数による文字列配列の動的確保
投稿者---zero(2005/09/23 23:20:56)


>2次元配列っぽいので、sizeof(char**)×4かな?

それは違うと思います。

listが指すべきなのは"char *"の変数であり、その"char *"のための変数の領域をを4個分
確保するので"sizeof(char *) * 4"であってると思います。


この投稿にコメントする

削除パスワード

No.23270

Re:malloc()関数による文字列配列の動的確保
投稿者---あかま(2005/09/24 01:05:16)


そーでした。
返り値をchar**にするのと間違えてました。
失礼しました。


この投稿にコメントする

削除パスワード

No.23268

Re:malloc()関数による文字列配列の動的確保
投稿者---まきじ(2005/09/24 00:02:35)


>/* それぞれの文字列配列の領域として10文字分確保 */

一つずつ malloc() しなくても for 文で

int main(void){

    char **list;
    int i;
    
    list = malloc(sizeof(char*)*4);
    
    for(i = 0; i < 4; i++) list[i] = malloc(sizeof(char) * 128);
    
    return 0;
}
とすれば、list[4][128] と同じ様に扱える
二次元配列の領域が確保されます。


この投稿にコメントする

削除パスワード

No.23269

Re:頭の整理ができました(ありがとうございました)
投稿者---zero(2005/09/24 00:07:46)


>for(i = 0; i < 4; i++) list[i] = malloc(sizeof(char) * 128);
>とすれば、list[4][128] と同じ様に扱える
>二次元配列の領域が確保されます。

その通りですね。今回質問させて頂き頭の整理ができました。
ご回答して下さった皆樣ありがとうございました。


この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧