C ポインタ 新しいページはコチラ
提供: yonewiki
(→ポインタ) |
(→ポインタ) |
||
101行: | 101行: | ||
アドレス覚えるだけだから、ポインタの宣言で型名なんているの?って思った人はC言語初心者の中でも少し洞察力が高いと思う。残念ながら型名はいります。その指し示しているアドレスからどこまでを変数として使っているかを把握する必要があるからです。代入もできるわけですから、さらには、変数が配列になっている場合には、インクリメント演算子で次の配列番号に移動できたりもします。まぁ少しづつ応用していきましょう。ここではポインタとは何かを理解できればよいと思います。文字列は配列ありきなので、ポインタの扱いがさらに複雑化してきますし、構造体やクラスのポインタも複雑な操作が必要になります。<br /> | アドレス覚えるだけだから、ポインタの宣言で型名なんているの?って思った人はC言語初心者の中でも少し洞察力が高いと思う。残念ながら型名はいります。その指し示しているアドレスからどこまでを変数として使っているかを把握する必要があるからです。代入もできるわけですから、さらには、変数が配列になっている場合には、インクリメント演算子で次の配列番号に移動できたりもします。まぁ少しづつ応用していきましょう。ここではポインタとは何かを理解できればよいと思います。文字列は配列ありきなので、ポインタの扱いがさらに複雑化してきますし、構造体やクラスのポインタも複雑な操作が必要になります。<br /> | ||
+ | |||
+ | |||
+ | ポインタが配列になる場合の例 | ||
+ | <syntaxhighlight lang="cpp"> | ||
+ | int pnIntArr[3] = {100,110,120}; | ||
+ | int* pnIntArrPos; | ||
+ | |||
+ | printf("★pnIntArrPosポインタ変数出力(配列操作)\n"); | ||
+ | pnIntArrPos = pnIntArr;//pnIntArr配列の先頭アドレスをpnIntArrPosに。pnIntArrPos = &pnIntArr[0];と同じこと。 | ||
+ | printf("pnIntArrPos + 0 :%d\n",*pnIntArrPos); | ||
+ | |||
+ | pnIntArrPos = pnIntArrPos + 1;//ポインタ変数に整数値を加えると、ポインタ変数の型のサイズだけアドレスが進む。つまり次の配列のアドレスになる。 | ||
+ | printf("pnIntArrPos + 1 :%d\n",*pnIntArrPos); | ||
+ | |||
+ | pnIntArrPos = pnIntArrPos + 1;//繰り返しアドレスを進めてみる。 | ||
+ | printf("pnIntArrPos + 2 :%d\n",*pnIntArrPos); | ||
+ | printf("\n"); | ||
+ | |||
+ | //pnIntArrで宣言した配列もポインタ変数 | ||
+ | printf("★pnIntArr配列変数出力(配列はポインタであることを示す)\n"); | ||
+ | |||
+ | printf("pnIntArr + 0 :%d\n",*pnIntArr); | ||
+ | |||
+ | //ポインタ変数のアドレスを変更しないで、出力する例 | ||
+ | printf("pnIntArr + 1 :%d\n",*(pnIntArr + 1));//*(pnIntArr + 1)は、pnIntArr[1]と同じです。 | ||
+ | |||
+ | printf("pnIntArr + 2 :%d\n",*(pnIntArr + 2));//繰り返し次の要素も出力。 | ||
+ | printf("\n"); | ||
+ | |||
+ | //*(pnIntArr + 2)のカッコを付け忘れると、*pnIntArr + 2 は、*(pnIntArr) + 2 のような解釈で、0番目の要素 + 2になっちゃいます。 | ||
+ | printf("★pnIntArr配列変数出力の指定間違い\n"); | ||
+ | printf("(pnIntArr) + 2 :%d Miss!\n",*pnIntArr + 2); | ||
+ | </syntaxhighlight> | ||
+ | 出力結果 | ||
+ | <syntaxhighlight lang="text"> | ||
+ | pnIntArrPosポインタ変数出力(配列操作) | ||
+ | pnIntArrPos + 0 :100 | ||
+ | pnIntArrPos + 1 :110 | ||
+ | pnIntArrPos + 2 :120 | ||
+ | |||
+ | ★pnIntArr配列変数出力(配列はポインタであることを示す) | ||
+ | pnIntArr + 0 :100 | ||
+ | pnIntArr + 1 :110 | ||
+ | pnIntArr + 2 :120 | ||
+ | |||
+ | ★pnIntArr配列変数出力の指定間違い | ||
+ | (pnIntArr) + 2 :102 Miss! | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | 最初に配列を勉強すると、このようなポインタの表現が理解しづらいものに感じられますが、配列の[]を使った表現はポインタ変数の特殊な表記方法と思った方がいいのかもしれません。[]で配列を定義するとアドレス変数としての意識が薄れ、配列変数がポインタの役割をもっていることを忘れてしまいそうになります。例えば int a[1] = {200 , 210};のように定義するとaというint型の変数を定義したかのように錯覚してしまって混乱するのだと思います。それで、printf("%d", a);で要素0番目の出力をしようとしたりする間違いをしてしまうだろうなぁと思う。 | ||
+ | |||
+ | |||
+ | だから自分は配列の[]を使った時はポインタの変数としての役割と同じものを宣言したことを意識するべくpというプレフィックスを付けて、その後に型名のプレフィックスとしてintならn、charならc、wchar_tならwcという名前をつけ、配列にはStrもしくはArrという表記をつけるようにしています。そうすると、 | ||
+ | |||
+ | int pnAArr[1] = {200,210}; | ||
+ | |||
+ | char pcStrComment[] = ”コメント”; | ||
+ | char cSingle = ’A’; | ||
+ | |||
+ | のように定義でき、あとからpcStrCommentはポインタで、char* pcStrPos; char* pcPos; のような変数で pcStrPos = pcStrComment;という代入がプレフィックスが一致していることで正しいアドレス代入だと確信できます。 これを配列を使ったがばっかりにchar cStrComment[] = ”コメント”;としてしまうと pcPos = &cSinge; のようにできるとして pcStrPos = cStrComment; って&がいるんだっけ?という迷いはなくなります。 | ||
+ | |||