配列のディスプレイとは何か

このQ&Aのポイント
  • 配列のディスプレイとは、配列のアドレスへのポインタ配列のことです。
  • 配列のアドレスを格納するためには、char型ではなく、適切なデータ型を使用する必要があります。
  • 配列のアドレスを配列にして使う場合、どのように活用するか理解することが重要です。
回答を見る
  • ベストアンサー

配列のディスプレイという使い方について

先程は、ありがとうございました もうひとつ、お願い致します 「配列へのポインタ配列」 これは、配列のディスプレイという使い方についての説明です 以下がコードです int hoge1[10]; int hoge2[10]; int hoge3[10]; int *chobi[3]={hoge1,hoge2,hoge3}; まず、コードを見る限り、これは「配列のアドレスへの配列」と言えばよいのではないでしょうか 「ポインタ配列」とは、 *foo() こういうものだと認識しています (「配列へのアドレスの配列」が正しいかもしれません。容赦してください) 「配列へのポインタ配列」という表現が、全く理解できません どなたか説明お願い致します 次に、配列のアドレスを格納するのであれば char 型にするべきではないでしゅうか(アドレスは16進数なので) 最後に、使い方がわかりません 配列のアドレスを配列にして、どのように使うのでしょうか 以上、質問が多いですが、よろしくお願い致します

noname#192849
noname#192849

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

  • ベストアンサー
  • KEIS050162
  • ベストアンサー率47% (890/1879)
回答No.3

この場合、*chobi[]は、ポインタ配列と呼ぶのが正しいですね。 ポインタが格納された配列で、要素0、1、2、にhoge1、hoge2、hoge3のポインタが格納されています。 参考: http://www.wakhok.ac.jp/~kanayama/C/98/node110.html char や int は変数の型を指定するものです。 char なら 8bit 、int なら 16bit の符号付き整数の表記という意味です。 アドレスが入っているから、変数の型が変わるということはありませんし、16進数だから char ということもありません。 int 型の変数が入っているアドレスが格納されるのがポインタということです。 ポインタと型の関係は非常に重要で、例えば int型の場合、 hoge1[0] が 0x1000 に格納されているとすれば、 hoge1[1] は、0x1002 に格納されますが、 もし、これがchar型なら、 hoge1[0] が 0x1000 に格納されているとすれば、 hoge1[1] は、0x1001 に格納されることになります。 即ち、配列を1加算すると、それにより参照されるアドレスは格納されている変数のBit数分加算されるということです。 どんな風に使うか? 下記にポインタ配列を使ったサンプルを載せておきます。 入力した数値により、表示する文字列のポインタを printf 関数に渡している例です。 #include <stdio.h> void main(void) { int hoge1[10] = { 'R','e','d'}; int hoge2[10] = { 'B','l','u','e'}; int hoge3[10] = { 'G', 'r', 'e', 'e', 'n' }; int *chobi[3]={hoge1,hoge2,hoge3}; int k; while( 1 ) { printf("input Color No. = "); scanf( "%d", &k ); if (k > 2 ) break; printf("\n Color = %s\n",chobi[k]); } printf("Good Bye\n"); return 0; } ポインタを使うと、引数として要素を全部渡す必要がないので、メモリを節約出来るばかりでなく、コードもスッキリします。 この他にも、関数のポインタを配列にして、引数により異なる関数を実行させるなど、便利な使い方はたくさんあります。 http://www5c.biglobe.ne.jp/~ecb/c/16_04.html C言語を学ぶ最初に出てくるのが変数の型だと思いますので、もう一度しっかり復習して、型と数値表現をしっかり理解してみてください。 その上で、ポインタとは? と進んだ方が良いですね。 ポインタ、ポインタ配列などがしっかり理解出来ていれば、構造体、共用体にすんなり入っていけると思います。 ご参考に。

noname#192849
質問者

お礼

度々、ありがとうございます 文字列テーブルとか関数テーブルとか言われる使い方は、一通り勉強したはずなのですが、ちょっと変則的になると理解できなくなるのは、基本ができていないからだと思いました 仰るとおり、変数の型や数値表現から復習してみようと思います

その他の回答 (3)

  • chie65535
  • ベストアンサー率43% (8522/19371)
回答No.4

>まず、コードを見る限り、これは「配列のアドレスへの配列」と言えばよいのではないでしょうか 違います。 それを言うなら「アドレスの配列」か「『配列へのポインタ』の配列」です。 アドレスの指す先に、偶然、配列があるに過ぎないのです。 それに「への」の使い方も間違っています。「への」が使えるのは「○○へのポインタ」と言う場合だけです。 「○○へのポインタ」ってのは言い換えれば「ポインタが指し示すメモリの中身は○○型である」です。 「配列のアドレスへの配列」と言う、誤った表記を、上記のように言い換えると「配列が指し示すメモリの中身は配列のアドレス型である」と言う、意味不明な文章になっちゃいます。 「配列が指し示す」って意味不明です。「配列のアドレス型」も意味不明です。 と言うわけで。 実は「アドレスそのものは、自身が指すアドレスのメモリに、何があろうが感知しない」のです。 もし、アドレスの指す先が「配列」なのであれば、その「アドレス」は「配列へのポインタ」と言えます。 「アドレス」を「配列へのポインタ」に言い換えれば「『アドレス』の配列」と言う表記は「『配列へのポインタ』の配列」に言い換えられます。 >次に、配列のアドレスを格納するのであれば char 型にするべきではないでしゅうか(アドレスは16進数なので) char型にしたら「アドレスの指す先のメモリのデータは、char型である」になっちゃう。メモリの中には「intのデータ」が入っているのに、char型として取り出してしまって、変な事になる。 まず「アドレスは、型を持たない」と言うのを覚えましょう。 それに、アドレスは、16進数とは限りません。2進数で表現しても良いし、8進数で表現しても良いし、10進数で表現しても構いません。何進数にしようとも「値は同じ」ですからね。 「アドレス」ってのは「一丁目です」って言ってるだけです。 一丁目に犬小屋(char)が建っているか、一軒屋(short)が建っているか、高層ビル(intの巨大な配列)が建っているかは「ちゃんと言わないと判らない」のです。 >最後に、使い方がわかりません >配列のアドレスを配列にして、どのように使うのでしょうか 一番簡単なのは「二次元配列の代わりに使う」です。

noname#192849
質問者

お礼

ご指摘、回答ありがとうございます よくわかりました 時間のあるときに、この表現のしかたを整理してみようとおもいます

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

「配列へのポインタ配列」 が何を言っているのか, 私にもわかりません. そのような表現がどこにあったのか, 教えてもらっていいですか? ちなみに個人的には ・アドレス: オブジェクトが占めるメモリ上の「位置」を表す「もの」 ・ポインタ: アドレスを値とする変数 と思うといいんじゃないかなと考えていたりします. K&R が, これに近い表現をしてたような気がする. #1 の例で「アラインメントが違う」とどうなると「予想」していますか? そして, 実際に実行したらどうなりましたか?

noname#192849
質問者

お礼

回答ありがとうございます

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.1

> 「ポインタ配列」とは、 > *foo() > こういうものだと認識しています これだと、宣言なら「ポインタを返す関数f()」、実際の使用時なら「 f() の戻り値(ポインタ)の実体」になります。 ポインタは、実体のあるアドレスを示しています。 ポインタは型の一種、その内容はアドレス、という感じではないでしょうか。 int *chobi[3]={hoge1,hoge2,hoge3}; は、「int *(intへのポインタ)の配列」です。 その内容が「hoge1,hoge2,hoge3のアドレス(を表わすポインタ)」です。 > 配列のアドレスを格納するのであれば char 型にするべきではないでしゅうか(アドレスは16進数なので) char chobi[3]={hoge1,hoge2,hoge3}; ということですか? charはポインタではないので、型が一致しません。 それとも char* chobi[3]={hoge1,hoge2,hoge3}; ということですか? ポインタには、アドレスの他に、「実体の型」を示す役割りがあります。 int * p ; と宣言したpなら *p は int型です。 これだと、chobi[0] はchar *なので、 *(chobi[0])は、char型です。 これ本来は hoge[0] となることが期待されるでしょうが、hoge[0]はint型です。 long a = 0 ; long *p = &a ; /* aのアドレス */ char *q = (char *)(& a) ; /* 同じく aのアドレス */ printf("p: %p, q:%p\n", p,q ) ; /* p == q になる */ printf("p+1: %p, q+1:%p\n", p+1,q+1 ) ; /* p+1 と q+1では? */ これの実行結果、どうなるか予想できますか? 「アドレスは16進数」というのがそもそもの誤解です。 アドレスはただの値です。XX進数なんてものはありません。 入出力の際に都合のいい方法が使われているだけです。

noname#192849
質問者

お礼

回答ありがとうございます まず、誤字が目立っていたみたいで失礼致しました ポインタ配列は・・・こういうものだと認識しています *foo[] これの間違いでした ・・・char 型にするべきではないでしゅうか 仰るとおり、char* 型の間違いです でしゅうか→でしょうか コードまで書いていただいて、ありがとうございます 予想はできます long 型と char 型では、アライメントが違ってくるという認識でよろしいでしょうか >「アドレスは16進数」というのがそもそもの誤解です たいへん勉強になりました 「ただの値」だったのですね・・・ ひとつ謎が解けたので、スッキリしました よろしくお願いします

関連するQ&A

  • C言語の型と配列

    char* str[10]={"a","b"}; char* str2="c"; としたときにstr=str2とすると 型が合わないといったエラーが出ます。 でもstrって結局はポインタの配列の先頭要素のアドレスですよね。 ポインタにポインタを入れているので通るのかなと思ったんですけど、 配列で宣言するとポインタにも型がつくのでしょうか? この例だと strは char * を10個持つ配列をさすポインタ  で、 str2はchar *をさすポインタ みたいなかんじです。 質問の意味がわかりにくいですが、ご指摘をいただければ補足しますので よろしくお願いします。

  • 配列で混乱しています

    c言語を勉強中のものです。文字列を配列で扱う場合とポインタで扱う場合の違いにこんらんしています。 たとえば char str[] = "hello"; str = "goodby"; のように文字列の再格納はダメですが、 char *str = "helllo"; str = "goodby" は大丈夫です。 また char[100]; scanf("%s",str) は大丈夫ですが char *str; scanf("%s",str) はいけません。この2つの違いは何によるのでしょうか? またポインタはそもそも int a; int *pa; pa = &a; のように、宣言したあとはアドレスを入れる専用のハコのように考えていたのですが、 char *str = "helllo"; str = "goodby" のようにいきなりアドレスでない文字列を代入するのも納得がいきません。誰か解説をお願いします。

  • char* 宣言での配列要素アクセスについて

    char* 宣言での配列要素アクセスについて char*型で宣言したポインタ変数に対して 配列の要素でアクセスすると落ちてしまいます。 理由がよくわかりません。 以下コードになります。 (コードA) char* pA = "123456789"; pA[2] = 'A'; 以下のコードの場合は問題ありません。 (コードB) char pB[] = "123456789"; pB[2] = 'B'; 両者の違いがいまいちよく分かりません。 コードAでpA[2]のアドレスを確認すると、 pAのアドレス[+2]を指しているので問題ないともうのですが、 間違っているのでしょうか? pAに対して特別な操作はしていません。 ご教授お願いいたします。

  • 配列のポインタ配列のポインタから元の配列を参照する方法について

    C初心者です。下記の様に配列のポインタ配列を作って、そのポインタ配列のポインタを返すコードを書いて、main関数で元の配列の値を参照したいのですが、上手く参照できずに困っています。下記のコードの問題点も含めて、配列のポインタ配列のポインタから、元の配列の値を参照する方法を教えてください。お願い致します。 short int *motion_data(void) { short int data1[5][7] = { {2377,2174,0,0,0,0,0}, {2377,2377,2784,2648,2648,2648,2377}, {2377,2377,2784,2648,2648,2648,2377}, {2377,2377,2377,2377,2377,0,0}, {2377,2377,2377,2377,2377,0,0}, }; short int data2[5][7] = { {2377,2174,0,0,0,0,0}, {2377,2377,2919,2784,2784,2784,2377}, {2377,2377,2919,2784,2784,2784,2377}, {2377,2377,2377,2377,2377,0,0}, {2377,2377,2377,2377,2377,0,0}, }; short int *po_data[2]; po_data[0] = data1[0]; po_data[1] = data2[0]; return *po_data; }

  • 2次元配列とポインタ配列の違い

    2次元配列とポインタ配列の違いを比較するプログラムを作成したつもりなのですが、下のプログラムの printf("we[%d]=%u\n",i,&we[i][0]); という文がどうやら違うらしいのですが、全く分かりません。 なので、なんとなくでも構わないので分かる方がいらっしゃったらお願いします。 #include<stdio.h> int main(void) { int i; char *we[]={"Monday","Tuesday","Wednesday"}; char ek[][10]={"Monday","Tuesday","Wednesday"}; printf("2次元配列で格納したアドレス\n"); for(i=0;i<3;i++){ printf("ek[%d]=%u\n",i,&ek[i]); } printf("ポインタ配列のアドレス\n"); for(i=0;i<3;i++){ printf("we[%d]=%u\n",i,&we[i]); } printf("ポインタ配列で格納したアドレス\n"); for(i=0;i<3;i++){ printf("we[%d]=%u\n",i,&we[i][0]); } printf("ポインタ配列で格納した文字列\n"); for(i=0;i<3;i++){ printf("we[%d]=\%s\n",i,we[i]); } printf("2次元配列で格納した文字列\n"); for(i=0;i<3;i++){ printf("ek[%d]=\%s\n",i,ek[i]); } return(0); }

  • 多元配列について(ANSI C)

    動的多元配列で、 Voidポインタに、多種の型がぶら下がった多元配列を作り、 読み書きをしたいのですがどのようにしたらよろしいでしょうか。 具体的には、 x[0][1]は、intで「2」が入っている x[0][4]は、intで「9」が入っている x[1][2]は、charでしかも文字列の配列で「goo」が入っている x[1][5]は、charでしかも文字列の配列で「教えて」が入っている x[0]は、int型の配列。X[1]は、文字列型の配列。 というようなものです。 一応ソースは作ってみたのですが、int型では問題なくいくのですが、 文字列は、コンパイルはできますが、実行すると予期せぬことが起きます。 #include <stdio.h> #include <stdlib.h> #include <string.h> int main (void) {      void **topPointa;      int * iDataInput;      int * iDataOutput ;      char * chDataInput;      char * chDataInput2;      char * chDataOutput1 ;      // ポインタアドレス用のメモリ確保      topPointa = (void *) calloc (10 , sizeof(void *));      if(topPointa == NULL) {           printf("メモリが確保できません\n");           exit(-1);      }      //int配列のメモリ確保      iDataInput = (int * ) calloc (10 , sizeof(int));      if(iDataInput == NULL) {           printf("メモリが確保できません\n");           exit(-1);      }      iDataInput[0] = 3 ;      iDataInput[1] = 4 ;      topPointa[0] = (void * ) &iDataInput;      //int配列の取り出し      iDataOutput = *(int *) topPointa[0];      printf( "int: %d\n", iDataOutput[0] );      printf( "int: %d\n", iDataOutput[1] );      //char配列 のメモリ確保      chDataInput = (char * ) calloc (10 , sizeof(char *));      if(chDataInput == NULL) {           printf("メモリが確保できません\n");           exit(-1);      }      chDataInput2 = (char * ) calloc (10 , sizeof(char));      if(chDataInput2 == NULL) {           printf("メモリが確保できません\n");           exit(-1);       }      strcpy(chDataInput2 , "hoe");      chDataInput[0] = &chDataInput2;      topPointa[1] = (void * ) &chDataInput;      //char配列の取り出し      chDataOutput1 = *(char *) topPointa[1];      printf( "char: %S\n", chDataOutput1[0] );      free(iDataInput);      free(chDataInput);      free(chDataInput2);      return 0; } 言語は、C言語ANCI Cでお願いします。 以上。よろしくお願いします。

  • アドレス格納のための二次元配列のメモリ動的確保

    アドレス格納のための二次元配列のメモリ動的確保 二次元配列のためにメモリを動的確保しなければならないのですが、 その配列に格納したいものが 「DATA型のポインタ」です。(DATA型はtypedefした構造体です。) プログラム実行中にmallocで確保した、数あるDATA型の構造体の、その先頭アドレスを リストアップするための配列です。 この場合、どのような形でmallocすればよいのでしょうか? 教えていただけるとありがたいです。よろしくお願いいたします。 -- たとえば m×n のint型の配列は、 ◆ int *i; ◆ i = (int *)malloc( m * n * sizeof(int) ); となりますよね。 この要領がでやるのが一般的にわかりやすいものだとするならその方法でやりたい (後発の人が自分のソースコードを読む可能性があるため)のです。 -- 同様にm×nの「DATA型のポインタを格納するための二次元配列」を動的確保したい場合、 ◆ DATA *d; ◆ d = (DATA *)malloc( m * n * sizeof(DATA) ); この文にどのように付け加えたら良いのでしょう? もうあと一歩な気がするのですが(笑)。しかし参考書等で勉強しましたがわかりませんでした・・・。 わかる方、どなたかよろしくお願いいたしますm(_ _)m あとこれだけ通ればコンパイルが通るんです!!!!! たぶん(笑)

  • ポインタ配列

    "one","two","three","four","five","six","seven","eight","nine","ten" のポインタ配列の文字列を、ASCIIコード順に並べ変えようと思ったのですが、 もうどこが間違っているかさえわからないぐらいになってしまいました。 まだまだはじめたばかりなもので、わからないことだらけなんで、 できるだけわかりやすい説明おねがいします。 関数の引数に問題があるのじゃないかと思ったのですが、 何かいいアドバイスありましたら、お願いします。 #include <stdio.h> /* 関数のプロトタイプ宣言 */ int strmp(char *,char *); void cpy(char *,char *); int main (void) { /* ポインタ配列の定義 */ char *x[10]={"oneee","twooo","three","fourr","fivee","sixxx","seven","eight","ninee","tennn"}; /* ポインタのポインタの定義 */ char **pp=x; char k[100]; char *p=k; int i,t,a,b,c,d; a=0; /* ポインタ配列を自作関数を使って、ASCIIコードの大きいほうからに並び替える */ for(i=0;i<9;i++) { for(t=1;t<10;t++) { a=strmp(*(pp+i),*(pp+t)); if(a<0) { cpy(p,*(pp+i) ); cpy(*(pp+i),*(pp+t) ); cpy(*(pp+t),p); } } } for(i=0;i<10;i++) { printf("%s ,",x[i]); } printf("\n"); return 0; } /* 文字の比較をする関数 */ int strmp(char *x,char *y) { int i; for(i=0;*(x+i)==*(y+i);i++) { if( *(x+i)=='\0') { return 0; } } return *(x+i)-*(y+i); } /* 文字をコピーする関数 */ void cpy(char *a,char *b) { int i; for(i=0;*(b+i)!='\0';i++) { *(a+i)=*(b+i); } *(a+i)='\0'; }

  • DXライブラリ:ポインタと配列?

    初心者です。よろしくお願いします。 C言語とDXライブラリを利用してゲームを作成中です。 GetMousePointの関数を利用して、マウスの座標がその時、どこにあったのか。という情報を配列に格納したい、と考えています。 リファレンスページを参照すると、 int GetMousePoint( int *XBuf, int *YBuf ); このように書かれているのですが、配列に格納しようとするとフリーズしてしまいます。 【1】 GetMousePoint(&x,&y); zahyou[i] = x; 最初上のようにしてフリーズしたため、ああ、アドレスを格納してしまったのか。と思いまして、 下のように直しました。 【2】 GetMousePoint(&x,&y); int *a = &x; zahyou[i] = *a; が、またフリーズが発生しました。ポインタを説明しているページを見てはいるのですが、ポインタの指すアドレスの中にある数値の取り出し方がイマイチ掴めません。 なぜか別の場所で処理している、 【3】 (x = x-230)/=40; x = x*40+250; このような処理に関しては動くのですが・・・。これはアドレスを直接に利用している、ポインタの中身を利用しているのではない、ような気がするのですが、なぜか動いています。 (上の処理より下の箇所で利用しています) 【1】【2】【3】のそれぞれがどう言った処理を行っていて、こうすれば良い。等のアドバイスをいただけないでしょうか。 あつかましいとは思いますが、よろしくお願いします。

  • C言語 配列

    ご質問させていただきます。 CSVファイルからデータを呼び出し、二次元配列として出力したいのですが上手くいきません。 CSVファイルには英数字が混ざっており、エクセルでいう、11行と1440列ほどのデータがあります。初心者なりに書いてみたのですが、どこから手を付けたらいいかわかりません。 三次元配列にしないといけないとのアドバイスをいただいたのですがどのようにすればいいかわかりませんヒントを頂けるとたすかります。 元のcsvファイルは例ですがこのような下記のような構造になっていて2行目にいったときに[0][0]から[1][0]と変わっていってほしいです。 testt,esttest,testte,stte,sttest testte,sttes,ttest,~ 理想 [0][0] = [testtesttest] [0][1] = [testtesttesttest] 一行が終わりしだい [1][0] = [testtesttesttest] と変わっていくようにしたいです。 エラーが出ますが、コードを記載させていただきます。 コード #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> int main(void) { //ストリームポインタ FILE *fp; int kk = 0; int nn = 0; int hoge; //ファイルから読み込んだテキスト1行分を格納するためのchar配列を指定します int piyo[11][1440]; //*filename : 開くファイル名を指定 char *fname = "./test1/test2/201509/test.csv"; //ファイルが無かったり,指定フォルダでなければ、FILE変数fpはNULLが返ります。 fp = fopen(fname, "r"); //NULLが返ってきた場合の処理 if (fp == NULL) { printf("%sファイルが開けません¥n", fname); return -1; } //ファイルから1行ずつ読み込む成功すると、読み込んだ文字列のポインタを返し、失敗すると、NULLを返します。 while (1 == fscanf(fp, "%c,", &hoge)) { piyo[kk][nn] = hoge; printf("[%d][%d]=%d\n", kk, nn, piyo[kk][nn]); nn++; if (1440 == nn) { kk++; nn = 0; } } //FILE *fp : fopen()で取得したファイルポインタ fclose(fp); return 0; }

専門家に質問してみよう