• ベストアンサー

ポインタ配列の動的確保

ポインタの配列の動的確保について教えてください。 入力した数値をポインタ配列に入れるプログラムです。 下記のように書いてみました。(見づらくてごめんなさい) #include<stdio.h> #include<stdlib.h> #define kensu 3 main() { char abc[kensu+1]={'A','B','C','\0'}; char *ptr[kensu]; int i; printf("3つの整数を入力して下さい。\n"); for(i=0;i<kensu;i++){ ptr[i]=(char*)malloc(sizeof(char)*10); if(ptr[i]==NULL){ printf("メモリの取得に失敗しました"); exit(1); } printf("整数%c:",abc[i]); fgets(ptr[i],10,stdin); if(ptr[i][strlen(ptr[i])-1]=='\n') ptr[i][strlen(ptr[i])-1]='\0'; } for(i=0;i<kensu;i++) free(ptr[i]); } ちゃんと動いているようです。 しかし、ポインタ配列の動的確保をネットで調べてみると、ポインタのポインタ(?)を使って、下記のように2度mallocしています。 #include <stdio.h> #include <stdlib.h> #define N 3 int main(void) { char** arr; int i,j; arr = (char**)malloc(N * sizeof(char*)); /* ポインタ配列を確保 */ /* 配列の要素それぞれにつき、メモリ領域を確保 */ for(i=0;i<N;i++) arr[i] = (char*)malloc(N * sizeof(char));   ・・・ ポインタの配列を宣言して、配列の各要素に動的確保するのと ポインタのポインタを宣言し、ポインタ配列を動的確保して、再度配列の要素に動的確保するのとでは、何か違いがあるのでしょうか? ポインタのポインタを宣言し、ポインタ配列を確保する必要性が良く分かっていないのです。 ネット等で調べて見たのですが、理解力がないのかよく分かりませんでした。 どうか教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
  • koedame
  • ベストアンサー率33% (10/30)
回答No.3

質問の内容では3件と断定しているので、ポインターの配列要素が 既に決まっていますが、ポインターのポインターを使えば int a; char **strList; printf("最初に何件入力しますか?"); scanf( "%d", &a ); strList = (char**)malloc(a * sizeof(char*));//件数確保 //この時点で件数がa個確保されます。 //例:a=5;の時char *strList[5]; に変化します。 for(int i=0; i<a; i++) { strList[i]=(char*)malloc(10 * sizeof(char));//10文字分確保 } //この時点でa=5のとき char strList[5][10]; になります。 別件 他にも領域の違いもあります。 ポインター配列の場合 char *p1[10]; 宣言時にchar * 型の配列を10個、処理系によって違いますがたいていポインターは4バイト計算ですのでここでは4バイトで話すと、 4×10=40バイト領域を宣言時に確保します。 ポインターのポインターは char **p2; ポインターをポインターにしても4バイトなので、 この場合は宣言時は4バイトしか確保しません。 ポインター配列は配列数が大きければ多いほどポインターとはいえ 容量を宣言時から結構使いますから、 領域を節約したいならポインターのポインターで、 まあ、そんな大きなプログラムでもなさそうなので ポインターのポインターはまだ触れないほうがいいでしょう。

empuru
質問者

お礼

koedame様 丁寧なご回答をありがとうございます!! とても分かりやすいです。 確保する領域についてはまったく考えていなかったので、目からウロコでした。 ポインタの配列でも、とりあえずは確保することができるのですね。 ポインタのポインタは難しくてあまり使わないようにしていたのですが、今回教えていただいて利点が分かったので、使ってみようと思います。 本当にどうもありがとうございました。

その他の回答 (2)

  • driverII
  • ベストアンサー率27% (248/913)
回答No.2

#1 です。 ちょっと補足すると、質問中、後者のプログラムでは、 (要素の方の確保時、確保しているのがchar 3 バイトで? と思いますが) #define N で宣言してますが、変数(int N; で宣言)にして可変にしても動作しますが、 前者のプログラムだと char *ptr[kensu]; は、char *ptr[3] としてコンパイルされ、 int kensu; char *ptr[kensu]; だと、処理系によってはエラーになります。 よって、件数を可変なら後者、件数が固定(3件)なら前者 というわけです。

empuru
質問者

お礼

driverII 様 お礼がおそくなりまして、ごめんなさい!! ご回答ありがとうございます。 なるほど・・・確かに3件と確定の場合は配列の要素数に指定できますが、3という値を変更することはできないです。 ポインタのポインタで動的に確保すれば、その件数も変更できるということなのですね! 勉強になりました。 ご丁寧に説明してくださり、ありがとうございました。

  • driverII
  • ベストアンサー率27% (248/913)
回答No.1

件数を動的にしたい場合は、ポインタ配列を動的確保します。

関連するQ&A