目次
前
次
ポインタを使えるようにする
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でプログラムすることに慣れてくると
ポインタでの記述の方がわかりやすく
感じます。
ポインタを使うときには、エンディアンの意識も
必要になります。
数値がメモリの中に入っているときには、アドレスの
小さい方に下位桁をいれるのが、リトルエンディアン。
アドレスの小さい方に上位桁が入るのが、ビッグエンディ
アンになります。
目次
前
次