プロが教える店舗&オフィスのセキュリティ対策術

No.847223 reallocについて
No.847300 ポインタについて

と質問させてもらい、御回答をいただき、理解した(つもりな)のですが、以下のことが実現できなくこまっております。
(以前の質問はこれを実現するために質問しました。)


まず配列array[1][20]を用意します(つまり文字列最高20字格納できる要素数1個の配列を用意)。
そして動的にこの配列のサイズを変更して、なにか文字列を入力する毎に、代入するスペースを逐次確保したいわけです。(メモリが溢れない限りスペースを確保しまくる)

そこでcallocやreallocの記述の仕方に困っています。
まず、callocについて

char array[1][20];
char *pn, *pn2;

pn = (char *)calloc(sizeof(array)/sizeof(char),sizeof(char));

このボイドポインタをキャストする部分にchar* と
char** のどちらを使えばいいか、です。



そしてreallocについて、

if( (pn2 = (char *)realloc(pn, sizeof(array)*cnt)) == NULL ){

printf("メモリの確保失敗!\n");
exit(0);
}
pn=pn2;

strcpy(pn[cnt],input);

【ただし、cntは毎回1づつ増加する。】
【inputはchar型の配列で、なんらかの文字列がはいっている。】

としているのですが、これもキャストの仕方がわかりませんし、strcpyで、セグメンテーションフォルトになります。構造体を使ったリスト形式も考えたのですが、reallocの使いかたを覚えたいのであえてこの形式で実現しようとしています。

結局どうしたいかというと、realloc部をforループさせて、cntを1ずつ増加させ、
pn[1][20]
つぎは
pn[2][20]
つぎは
pn[3][20]
とどんどん増やしていきたいわけデス。


すこしわかりにくい説明だとおもいますが、不明点や、言い回しがオカシイ箇所があればご指摘下さい。

A 回答 (4件)

おっしゃるとおり、第一引数がNULLの場合の動作はmallocです。



typedefをしない場合は、それぞれ

char (*pn)[20] = NULL;



pn = (char(*)[20])realloc(pn, sizeof(char[20])*cnt);

となるのかな。ちと自信ないですが。
    • good
    • 0
この回答へのお礼

再び御回答ありがとうございました。

(char(*)[20])
という風にキャストするんですね...
(char [20] *)とやっていたのでエラーにひっかかって困ってました^^;

char (*pn)[20]
とは、「char型の要素数20個の配列へのポインタ」を宣言しているわけですよね?
なんとなくわかってきました!

#1の方にアドバイスしていただいた方法での解決方法もきになるのでそちらのほうもがんばってみます。

お礼日時:2004/05/03 22:31

『「20字格納できる配列」を指すポインタの配列』を増やすので。


char **array=NULL;
int i;
int n =5;
for (i=0; i<n; i++) {
array = (char**)realloc(array, sizeof(char*) * (i+1));
array[i] = (char *)calloc(20,1);
}
これで
char array[5][20];
であるかのように使える。
    • good
    • 0
この回答へのお礼

やはりこの方法だと多次元配列のように、array[0],array[1]の表すポインタが等間隔(20バイト)にならぶようなメモリ配置はできないんですね^^;最初は24バイト間隔になっていました。


mihano様の方法だと、
reallocでchar型ポインタの配列、array[0],array[1]と逐次確保していき、あたらしく割り当てられたarray[i]に、callocによって動的確保したchar型の要素数20個の配列の先頭アドレスをセットする。

こういう解釈でよろしいでしょうか。よろしければこの確認だけお願いします。

ところでこの方法でも、array[5][1]というアクセスができるのは驚ろきました。array[][]と記述は多次元配列しかできないとおもっていたのですが、(array[5])[1] という風に考えるとなっとくできました。

お礼日時:2004/05/03 23:18

まず、arrayがサイズの決定にしか使われていないようなので



typedef char ARRAY[20];

などするべきです。その上で、pnの型は

ARRAY* pn = NULL;

です。reallocでの確保は、

pn = (ARRAY*)realloc(pn, sizeof(ARRAY)*cnt);

となります。pn1は必要ありませんし、mallocやcallocも使う必要はありません。
    • good
    • 0
この回答へのお礼

nyan5504様の方法でとりあえずできました。ありがとうございます。

「C言語 関数の使いかた+作り方 完全制覇」という書籍をまた改めて確認したところ、pn部分には「NULLを指定してもよい」とかいてありました^^;また見落していました、すいません。。。 NULLを指定したときの動作はMALLOCと同じと考えてよろしいでしょうか?

ひとつだけ疑問なのですが、もしこれにtypedefを用いなければどうかけるのでしょう。。
頭が混乱して疑問ばかりが生じてしまって申し訳ないです。

お礼日時:2004/05/03 21:49

char array[1][20];


このような静的配列のサイズを変更することはできません。

逆に言えば、動的に確保すればreallocを使えるわけです。
char **array=(char**)malloc(sizeof(char*));
array[0] = (char *)calloc(20,1);
足りなくなったらarrayをreallocで確保しなおしていく。

キャストの仕方がわからないのは、確保したものが何で、何に使おうとしているのか分かっていないということでしょう。
    • good
    • 0
この回答へのお礼

>char **array=(char**)malloc(sizeof(char*));
>array[0] = (char *)calloc(20,1);

これを元にreallocを考えたのですが、どうしても思い付きませんでした。
array = (char **)realloc(20*cnt);
でしょうか?これだけではたとえばcnt=2のとき、array[1]の値はNULLだったので、array[1]=array[0]+20;としなくてはいけませんでした。さらにarray[1][0]という記述ができなかったので、たぶんこれもだめですよね。

array[1]=(char *)realloc(20*cnt);
ともやってみましたが、これは自分でもちがうのはわかります。

array[0]=(char *)realloc(20*cnt);
これもたぶんだめですよね。


mihano様の記述方法だと、どうreallocをつかって確保すればいいのでしょうか....

お礼日時:2004/05/03 21:11

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!