目次

ポインタを使えるようにする

 Cでプログラムを書くときには、ボスキャラとして
 ポインタが出てくることがあります。

 アセンブリ言語からプログラムを始めた人には
 ポインタがボスキャラになるのが理解できない
 ということが多いです。

 Cでプログラムするときには、メモリイメージが
 ないと、ポインタの理解ができないでしょう。

 メモリイメージは、以下。



 アドレスは、バイトごとに振っています。

 アドレスとデータの2種のパラメータが
 あることをイメージで捉えておきます。

 ポインタは、アドレスを扱うことを理解すれば
 使い方は簡単。

 Cのデータ型は、データ側のサイズを示すために
 使うというのが大原則になります。

 次の変数宣言は、データに対しての名前付け。

  char x ;

  x = 0x12 ;

 この宣言では、メモリイメージでみると
 右のdataの方のどこかに変数名をつけた
 と同じ。



 この宣言で、値が入っているアドレスを
 取り出したいときには、&をつけます。



 ampersand と address の単語の先頭文字の
 a をかけて表現しています。

 dataの方に、名前をつけたので、そのときに
 アドレスを知りたいならば、&をつけて表現
 するというのが、Cのお約束。

 dataに変数名をつけられるなら、addressにも
 変数名をつけてよいではないか。

 addressに変数名をつけたなら、*(asterix)を
 つけて、dataを表現しよう。addressではない
 という否定を、*(asterix)にすればよい。
 これなら混乱しない。

 というのが、Cの設計思想です。

 addressに変数名ptrをつけると、dataは*を
 つけるので、次のように表記。

  char *ptr ;

  *ptr = 0x56 ;

 メモリイメージで考えると、以下。



 単純な命名の規則ですが、次のように覚えると
 よいでしょう。

 dataに対して命名を持って、宣言とする。
 もし変数名に否定の*をつけていると、その
 変数名はaddressにつけた変数名でポインタ
 になる。

 ポインタは、指示するモノというイメージ。

 アドレスは固定なのに対して、ポインタは可変になると
 カラクリを理解しやすいでしょう。

 気をつけなければならないのは、ポインタは
 指定するdataのサイズとは、異なるサイズを
 もっているということ。

 Cでは、変数のサイズは、そのコンピュータに
 合わせてよいので、ポインタは、そのaddress
 を2バイト、4バイト等のサイズをもってよい
 という規定になります。

 ここまでに説明した内容を入れないで、ポインタ
 を扱っている書籍が多数あります。

 データ型は、dataとして、1バイト、2バイト
 4バイト、8バイト、16バイトをもてるので
 それに合わせた宣言になります。

 32ビットのコンピュータでは、次のように
 なることもあります。

  char xx  ; /* 1 byte */
  short yy ; /* 2 byte */
  int   zz ; /* 4 byte */
  long  uu ; /* 8 byte */

 Cは、そのコンピュータに合わせたサイズの
 データ型としてよいので、コンパイラ依存
 のサイズになります。

 PICのような8ビットで使うコンパイラの
 一部には、次のようなサイズをもっている
 こともあります。

  char xx  ; /* 1 byte */
  short yy ; /* 1 byte */
  int   zz ; /* 1 byte */
  long  uu ; /* 2 byte */

 それでも、PICのコンパイラでは、ポインタの
 サイズは2バイト固定が多いです。

  char  *xptr ; /* 2 byte */
  short *yptr ; /* 2 byte */
  int   *zptr ; /* 2 byte */
  long  *uptr ; /* 2 byte */

 どのサイズになっているのかは、コンパイラの
 マニュアルを読むしかないのですが、最近では
 32ビットマイコンが普及したこともあってか
 ポインタは16ビットか32ビットが多くなりました。

 面倒なので、次のように覚えておくとよいでしょう。

 ポインタのサイズは、コンピュータのもつ
 アドレス空間のサイズにより決まる。

 昔のコンピュータである、Z80ではメモリアドレス
 は、最大64kバイトだったので、ポインタのサイズ
 は16ビットでよいのです。

 32ビットのマイコンで、アドレス空間が1Mバイト
 であれば、24ビットをカバーできる32ビットにして
 おけば、拡張性を考えても問題はなくなります。

 次のような図を描いて、少し計算するとポインタの
 サイズがわかるはず。



 メモリイメージが理解できれば、文字列の扱いは
 配列でなくても良いとわかります。

 文字列は、デリミタとして0を使うので
 以下が、メモリイメージになります。



 配列とchar型は、バイトで連ねたデータブロックと
 みなせるので、以下の処理は等価。

  char msg[6] ;
  /* array handling */
  msg[0] = 'H' ;
  msg[1] = 'e' ;
  msg[2] = 'l' ;
  msg[3] = 'l' ;
  msg[4] = 'o' ;
  msg[5] = '\0' ;
  /* pointer handling */
  *(msg+0) = 'H' ;
  *(msg+1) = 'e' ;
  *(msg+2) = 'l' ;
  *(msg+3) = 'l' ;
  *(msg+4) = 'o' ;
  *(msg+5) = '\0' ;

 Cでプログラムすることに慣れてくると
 ポインタでの記述の方がわかりやすく
 感じます。

 ポインタを使うときには、エンディアンの意識も
 必要になります。

 数値がメモリの中に入っているときには、アドレスの
 小さい方に下位桁をいれるのが、リトルエンディアン。
 アドレスの小さい方に上位桁が入るのが、ビッグエンディ
 アンになります。


目次

inserted by FC2 system