- ベストアンサー
配列の動的確保
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] とどんどん増やしていきたいわけデス。 すこしわかりにくい説明だとおもいますが、不明点や、言い回しがオカシイ箇所があればご指摘下さい。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
おっしゃるとおり、第一引数がNULLの場合の動作はmallocです。 typedefをしない場合は、それぞれ char (*pn)[20] = NULL; と pn = (char(*)[20])realloc(pn, sizeof(char[20])*cnt); となるのかな。ちと自信ないですが。
その他の回答 (3)
『「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]; であるかのように使える。
お礼
やはりこの方法だと多次元配列のように、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] という風に考えるとなっとくできました。
- nyan5504
- ベストアンサー率42% (6/14)
まず、arrayがサイズの決定にしか使われていないようなので typedef char ARRAY[20]; などするべきです。その上で、pnの型は ARRAY* pn = NULL; です。reallocでの確保は、 pn = (ARRAY*)realloc(pn, sizeof(ARRAY)*cnt); となります。pn1は必要ありませんし、mallocやcallocも使う必要はありません。
お礼
nyan5504様の方法でとりあえずできました。ありがとうございます。 「C言語 関数の使いかた+作り方 完全制覇」という書籍をまた改めて確認したところ、pn部分には「NULLを指定してもよい」とかいてありました^^;また見落していました、すいません。。。 NULLを指定したときの動作はMALLOCと同じと考えてよろしいでしょうか? ひとつだけ疑問なのですが、もしこれにtypedefを用いなければどうかけるのでしょう。。 頭が混乱して疑問ばかりが生じてしまって申し訳ないです。
char array[1][20]; このような静的配列のサイズを変更することはできません。 逆に言えば、動的に確保すればreallocを使えるわけです。 char **array=(char**)malloc(sizeof(char*)); array[0] = (char *)calloc(20,1); 足りなくなったらarrayをreallocで確保しなおしていく。 キャストの仕方がわからないのは、確保したものが何で、何に使おうとしているのか分かっていないということでしょう。
お礼
>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をつかって確保すればいいのでしょうか....
お礼
再び御回答ありがとうございました。 (char(*)[20]) という風にキャストするんですね... (char [20] *)とやっていたのでエラーにひっかかって困ってました^^; char (*pn)[20] とは、「char型の要素数20個の配列へのポインタ」を宣言しているわけですよね? なんとなくわかってきました! #1の方にアドバイスしていただいた方法での解決方法もきになるのでそちらのほうもがんばってみます。