• ベストアンサー

Wポインタを教えて下さい!

Wポインタってどういう時に使うものなのですか? ポインタを使ったリスト関数とどこが違うのですか? Wポインタを使う利点は・・・? 頭がこんがらがってしまいます。 もう半年くらい考えてるんですけどよくわからないのです。 どなたか教えて頂けるとありがたいのですが・・・。

  • meal
  • お礼率65% (28/43)

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

  • ベストアンサー
  • haporun
  • ベストアンサー率40% (230/562)
回答No.3

Wポインタという言葉は聞いたことはありませんが、それがポインタのポインタというなら、それを説明しましょう。 ポインタのポインタは、ポインタの配列の先頭アドレス絵を格納したものです。 その配列の要素それぞれは、ポインタなわけですから、それらもある配列の先頭アドレスをさしています。 要素へのアクセスは、2次元配列と同じように、c[5][7]などとして行います。 しかし、問題なのは変数を宣言しただけではそれぞれが有効なアドレスをさしていないということです。 ここに、どこかで宣言したローカルな配列のアドレスを入れたのでは意味がありません。 通常は、malloc関数やnew演算子が返した、動的なメモリのアドレスを格納します。 さて、使い道です。 2次元配列と似てますから、リストにもなります。 しかし、わざわざ2次元配列を使わないのは、別の目的があるからです。 このリストの列の数、行の数は、実行時に変化しなければなりません。 たとえば、まず、リストの行の数は実行時に8と決定され、さらに、1行目は12列、2行目は4列、3行目はなし、4行目は・・・。 このようなことは、2次元配列の大きさをあらかじめ十分にとっておけばできることです。 1行目は12列全部、2行目は4列しか使わないから5列目から12列目は無視・・・。 しかし、これではデータが多くなったときに、無駄なスペースが増えてしまいます。 そうならないようにするためには、動的なメモリの確保が必要なのです。 もう1つ例。 文字列は、それだけでcharの配列ですから、文字列をたくさん使おうと思ったら、それだけで2次元配列になってしまいます。 char x[7][12]; と宣言すれば、(NULLがあるから)11文字以下の文字列が7個出来上がります。 ただし、これでは各文字列が、必ず12バイト消費する上に、12文字以上を格納することができません。 これを、 char **x; x = (char**)malloc(7); x[0] = (char*)malloc(12); strcpy(x[0], "0123456789a"); x[1] = (char*)malloc(6); strcpy(x[1], "01234"); x[2] = (char*)malloc(25); strcpy(x[2], "0123456789abcdefghijklmn"); とやれば、必要な文字列の数も変化させることができ、各文字列の長さも自由自在です。 ちょっと考えれば、文字列の2次元配列(つまり、charの3次元配列)も簡単に扱えるようになります。 注意点としては、動的に確保したメモリは、必ず開放してやらないといけないということです。 ・・・さて、リスト関数ってのは私はわからないので悪しからず。 長々と書いてしまいました。 ポインタにはうるさい、はぽるんでした。

meal
質問者

お礼

ありがとうございました! なるほど、そのような使い方があったのですね・・・。 とてもわかりやすかったです。 また今後もよかったら教えて下さい!! 本当にありがとう!!

その他の回答 (2)

回答No.2

ダブルポインタ(ポインタのポインタ)をよく使う場合は、例えば2次元の配列を関数に渡したいときによく使います。 int arry[3][3]; こんな2次元配列が有るとします。 これをすべて1で初期化する関数は以下のようになります。 void func(a) int **a; { int i,j; for(i=0;i<3;i++) for(j=0;j<3;i++) a[i][j]=1; } これが一番良く使うやり方の例と思います。 関数内での左から一つ目のポインタは、配列の1次元目の先頭アドレスにあたります、2つ目も同様に配列の2次元目の先頭アドレスに対応します。 ふつう1次元配列を関数に渡す場合、ポインタ変数を受け側引数として宣言し、配列の先頭アドレスの値となる配列名を入力引数として渡します。 しかし2次元配列の場合、一つのポインタだけでは配列の1次元目のアドレス値しか受け取ってくれません。そこでこのように2次元目の配列にあたるアドレスを受け取れる様、ポインタをもう1つ付け加えてやっている訳です。 他にも色々有るかと思いますが思い浮かびませんこのくらいにしときます。 ちなみにダブルポインタがわかれば3つや4つも簡単ですが、果たしてそれが万人に受け入れられるかどうかは別の話です。 リスト構造の方が人間的に分かり易いですし、保守も簡単です。今の時代のマシン環境ならリストのオーバーヘッドもあまり気にならないでしょう。 たとえそのプログラムがとてもよく出来ていたとしても、mealさんが悩んだように、後になってそのソースを見る人も半年悩むとしたら時間の無駄になってしまいますしね。 なんだか半分セッキョウになってしまいましたがこんなところです。 参考URLは僕がこのごろ参考にしてるとこで、ダブルポインタを使ったプログラムとセッキョウが載ってたので付けときました。 それでは

参考URL:
http://www.ncad.co.jp/~komata/c-frame.htm
meal
質問者

お礼

ありがとうございます。 Wポインタは、ポインタの配列の、先頭アドレスを指すと考えていいのでしょうか? 参考URLもありがとうございました!! よかったらこれからも教えて下さい!

回答No.1

まず、ポインタを使ったリスト関数というのは何を指しているので しょう?リスト構造のことでしょうか?それを扱う関数のことでしょ うか?それとも全然別物? それから、Wポインタといわれても、何のことかよくわかりません。 双方向リスト構造のことでしょうか? double 型へのポインタってことではなさそうですが… 用語が正確でないと、何を答えていいかもわからなくて答えづらい です。

meal
質問者

お礼

お返事ありがとうございます。 wポインタですが、ポインタのポインタと呼ばれているものです。 リスト構造はポインタを使っていますが、 ポインタのポインタを使ってリスト構造を実現できるそうなのですが、 普通のポインタを使ったリスト構造とどこが違うのでしょうか? わざわざポインタのポインタを使う利点は? というようなことがわからないのですが・・・。 どうぞよろしくお願いします。

関連するQ&A

  • EM・ONEのようなポインタをW-ZERO3で

    EM・ONEのようなポインタをW-ZERO3で使うことはできますか? (W-ZERO3向けのものはありますか) また、その方法はどうなんでしょうか?

  • 関数ポインタの利点

    こんにちは。 C言語初心者ですが今勉強中です。 その中でポインタについては理解できたのですが、 関数ポインタの利点、使うべき所などが理解できません。 ポインタの基本は理解しています。 値渡し、アドレス渡しも理解しています。 関数ポインタを使うと何がいい、またはどんなとき使わなければならないのか 教本を読んでいてもさっぱりわかりません。 サンプルプログラムを打っても何のために使ってるのかわからないです。 どなたか教えていただけませんでしょうか? よろしくお願いします。

  • Voidポインタで受け取った変数の型を調べる方法

    あるライブラリの関数を利用しようとしたのですが、その関数の引数にVoidポインタがあり、どういう型のデータを格納したのかわかりません。このポインタのアドレスに格納されたデータの型を調べる関数なり方法なりというのはあるのでしょうか。 Voidポインタというのは型を問わずに受け取れるというのは利点ですが、受け取ったものがあらかじめなんだかわからない場合はどうするのでしょうか。よろしくお願いします。

  • voidポインタ

    曖昧な質問になってしまいますが、voidポインタを使うことによって どのような利点があるのかが解りません、あらゆるポインタ型から キャスト可能だということは解るのですが、具体的な使用方法がわかりません よろしくお願いします。

  • ポインタで詰まりました;

    こんばんわ、私は今仕事の合間をぬって独学でCとPerlを学んでいます。 まだやりはじめてから程無いのですが、ポインタに入ったところでつまづいてしまいました;(使い方がわからなくてパニックに; 以下の4つの問題、ポインタを使ったらどうやればいいのか教えてもらえないでしょうか? 1) 文字列の長さを求める関数を、ポインタを使って作成。 2) 文字列を比較する関数を、ポインタを使って作成。 一致の際(0)不一致の際は(1)を返す 3) 文字列中に含まれる、指定した文字の個数を求める関数を、ポインタを使って作成。 「what is this.」の場合、指定文字が「w」の場合は個数1を返す 4) 文字列中に含まれる単語の個数(スペースで区切られた部分)を求める関数を、ポインタを使って作成。 「ehat is this.」の場合、個数は3を返す。 私が今どのくらいの実力があるかといいますと、ほんと初心者同然です。 なので出来るだけ分かりやすく書いてくれると嬉しいです; よろしくお願いします(ノД`

  • ポインタのポインタが引数にある関数の使い方。

    ポインタのポインタが引数にある関数の使い方。 現在、このポインタのポインタが引数にある関数の動きがわからず困っています。 int test(int ** head) { int * pTail = (int *)*head; pTail = pTail + 1; } もし、この関数を呼び出して使用した場合どのような動きをするのでしょうか? int * comm_msg; これをグローバルポインタ変数として宣言させて、 test((void **)&comm_msg); このように呼び出したとした場合とさせていただきます。

  • 構造体配列のポインタについて(H17春基本情報試験C言語問題)

    平成17年春基本情報技術者試験の午後問題の問6について、質問があります。 設問dの答えがイなのですが、これがどうしても理解できません。 関数「int word_width(char *str, CHARPROF *char_list)」の「char_list」は構造体の配列のポインタとして宣言されています。 そしてこの関数内の処理を問う穴埋めdの解答は「*str != char_list[idx].char_p」となっています。 char_listは構造体配列のポインタなので、「char_list[idx]->char_p」あるいは「(*char_list[idx]).char_p」となるのでは?と思ったのですが、選択肢にもそれはありません。 char_list配列の先頭アドレスの中身を見るときは「char_list->char_p」となっても、要素番号がつくと、ポインタとはみなさなくなって「char_list[0].char_p」となるのでしょうか? だとするとポインタ宣言したchar_listとポインタ宣言しなかった場合(「CHARPROF char_list」のように普通に変数宣言?した場合)の「char_list[0].char_p」の違いがよくわからないのですが・・・。 念のため、この関数word_widthと構造体CHARPROFを転記します。 アドバイス、よろしくお願いします。 typedef struct {  char char_p; /* 文字 */  int char_w; /* 文字幅(ポイント数) */ } CHARPROF; int word_width(char *str, CHARPROf *char_list) {  int print_w = 0, idx;  while (*str != '\0') {   for (idx = 0; (ここに穴埋め「d」が入る); idx++);   print_w += char_list[idx].char_w;   str++;   }   return print_w; }

  • ポインタ引数をさらにポインタ引数に渡す方法

    ポインタ引数をさらに関数のポインタ引数として設定するには、 どうしたらよいのでしょうか? イメージとしては、 int 関数A(*a *b) { *a = 5; *b =3; 関数B(*a *b) } またポインタ引数の関数内で、 ポインタ指定せずに変数を使えるのでしょうか? int 関数A(*a *b) { a = 5; b =3; 関数B(*a *b) }

  • 関数へのポインタ

    超初心者です。 C言語を使ってsin波を生成して音を鳴らそうとしているのですが・・ネットで調べてもよくワカリマセン・・ 超初心者な私でも理解できるようなサイトを教えて下さい. また、関数へのポインタも勉強しているのですが, char *(*func)(void); といったchar 型へのポインタを返す関数へのポインタというのがあったとして,関数へのポインタは理解できたのですがさらにchar 型へのポインタとなると一体これが何を指しているのかさっぱりで・・・・ ご協力お願いします.

  • ポインタの参照

    ある関数でポインタをパラメータとして渡し、呼ばれた関数の中でさらにポインタ参照されたもののメンバを参照するにはどうしたらいいのでしょうか? サンプル   intRet = AAA(&p); ←関数を呼びます。   int AAA(TBL **p) { ↑   このポインタの中身を参照したい } どなたかわかる方いらっしゃいましたらお願いします。

専門家に質問してみよう