重要なお知らせ

「教えて! goo」は2025年9月17日(水)をもちまして、サービスを終了いたします。詳細はこちら>

【GOLF me!】初月無料お試し

先程は、ありがとうございました

もうひとつ、お願い致します

「配列へのポインタ配列」
これは、配列のディスプレイという使い方についての説明です
以下がコードです

int hoge1[10];
int hoge2[10];
int hoge3[10];
int *chobi[3]={hoge1,hoge2,hoge3};

まず、コードを見る限り、これは「配列のアドレスへの配列」と言えばよいのではないでしょうか
「ポインタ配列」とは、

*foo()

こういうものだと認識しています
(「配列へのアドレスの配列」が正しいかもしれません。容赦してください)
「配列へのポインタ配列」という表現が、全く理解できません
どなたか説明お願い致します

次に、配列のアドレスを格納するのであれば char 型にするべきではないでしゅうか(アドレスは16進数なので)

最後に、使い方がわかりません
配列のアドレスを配列にして、どのように使うのでしょうか

以上、質問が多いですが、よろしくお願い致します

A 回答 (4件)

この場合、*chobi[]は、ポインタ配列と呼ぶのが正しいですね。


ポインタが格納された配列で、要素0、1、2、にhoge1、hoge2、hoge3のポインタが格納されています。

参考:
http://www.wakhok.ac.jp/~kanayama/C/98/node110.h …

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)
{
inthoge1[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言語を学ぶ最初に出てくるのが変数の型だと思いますので、もう一度しっかり復習して、型と数値表現をしっかり理解してみてください。

その上で、ポインタとは? と進んだ方が良いですね。
ポインタ、ポインタ配列などがしっかり理解出来ていれば、構造体、共用体にすんなり入っていけると思います。

ご参考に。
    • good
    • 0
この回答へのお礼

度々、ありがとうございます

文字列テーブルとか関数テーブルとか言われる使い方は、一通り勉強したはずなのですが、ちょっと変則的になると理解できなくなるのは、基本ができていないからだと思いました

仰るとおり、変数の型や数値表現から復習してみようと思います

お礼日時:2013/06/27 16:11

>まず、コードを見る限り、これは「配列のアドレスへの配列」と言えばよいのではないでしょうか



違います。

それを言うなら「アドレスの配列」か「『配列へのポインタ』の配列」です。

アドレスの指す先に、偶然、配列があるに過ぎないのです。

それに「への」の使い方も間違っています。「への」が使えるのは「○○へのポインタ」と言う場合だけです。

「○○へのポインタ」ってのは言い換えれば「ポインタが指し示すメモリの中身は○○型である」です。

「配列のアドレスへの配列」と言う、誤った表記を、上記のように言い換えると「配列が指し示すメモリの中身は配列のアドレス型である」と言う、意味不明な文章になっちゃいます。

「配列が指し示す」って意味不明です。「配列のアドレス型」も意味不明です。

と言うわけで。

実は「アドレスそのものは、自身が指すアドレスのメモリに、何があろうが感知しない」のです。

もし、アドレスの指す先が「配列」なのであれば、その「アドレス」は「配列へのポインタ」と言えます。

「アドレス」を「配列へのポインタ」に言い換えれば「『アドレス』の配列」と言う表記は「『配列へのポインタ』の配列」に言い換えられます。

>次に、配列のアドレスを格納するのであれば char 型にするべきではないでしゅうか(アドレスは16進数なので)

char型にしたら「アドレスの指す先のメモリのデータは、char型である」になっちゃう。メモリの中には「intのデータ」が入っているのに、char型として取り出してしまって、変な事になる。

まず「アドレスは、型を持たない」と言うのを覚えましょう。

それに、アドレスは、16進数とは限りません。2進数で表現しても良いし、8進数で表現しても良いし、10進数で表現しても構いません。何進数にしようとも「値は同じ」ですからね。

「アドレス」ってのは「一丁目です」って言ってるだけです。

一丁目に犬小屋(char)が建っているか、一軒屋(short)が建っているか、高層ビル(intの巨大な配列)が建っているかは「ちゃんと言わないと判らない」のです。

>最後に、使い方がわかりません
>配列のアドレスを配列にして、どのように使うのでしょうか

一番簡単なのは「二次元配列の代わりに使う」です。
    • good
    • 0
この回答へのお礼

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

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

お礼日時:2013/06/27 16:12

「配列へのポインタ配列」


が何を言っているのか, 私にもわかりません. そのような表現がどこにあったのか, 教えてもらっていいですか?

ちなみに個人的には
・アドレス: オブジェクトが占めるメモリ上の「位置」を表す「もの」
・ポインタ: アドレスを値とする変数
と思うといいんじゃないかなと考えていたりします. K&R が, これに近い表現をしてたような気がする.

#1 の例で「アラインメントが違う」とどうなると「予想」していますか? そして, 実際に実行したらどうなりましたか?
    • good
    • 0
この回答へのお礼

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

お礼日時:2013/06/27 16:13

> 「ポインタ配列」とは、


> *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進数なんてものはありません。
入出力の際に都合のいい方法が使われているだけです。
    • good
    • 0
この回答へのお礼

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

まず、誤字が目立っていたみたいで失礼致しました

ポインタ配列は・・・こういうものだと認識しています

*foo[]

これの間違いでした

・・・char 型にするべきではないでしゅうか

仰るとおり、char* 型の間違いです
でしゅうか→でしょうか

コードまで書いていただいて、ありがとうございます
予想はできます
long 型と char 型では、アライメントが違ってくるという認識でよろしいでしょうか

>「アドレスは16進数」というのがそもそもの誤解です

たいへん勉強になりました
「ただの値」だったのですね・・・

ひとつ謎が解けたので、スッキリしました
よろしくお願いします

お礼日時:2013/06/27 14:09

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