C/C++ ポインタ入門 > ポインタの移動
Nobuhide Tsuda
Oct-2013
ポインタは移動可能だ
- ポインタとは任意のオブジェクトを指し、それを間接的に参照するためのものだ。
- 例えば、あなたが小さな会社の社長で、平社員が数10名いるとしよう
- 社員全員を集めて皆の前で命令を伝えることが出来ないと、
全ての社員をひとりずつ呼んで複雑な命令を伝えるのは結構大変だ。
- みんなに社長の命令を間接的に伝えてくれる課長がいたらどうだろうか?
- 社長のあなたは課長に一度だけ命令を伝えればよい
- 後は課長が平社員をひとりずつ呼んで、命令を伝えてくれる
- この課長に相当するのが「ポインタ」だ。
- ポインタの値を変更しながらポイント先を処理できるようになれば、一人前のポインタ使いへの第一歩だぞ。
int x, y;
int *ptr = &x; // ptr は x を指す
*ptr = 12; // x に 12 を代入
ptr = &y; // ptr は y を指す
*ptr = 34; // y に 34 を代入
ポインタが配列の要素を指している時、ポインタをインクリメント(+1)すると次の要素に移動するぞ
char v[10];
char *ptr = &v[0]; // ptr は v[0] を指す
*ptr = 12; // v[0] に 12 を代入
++ptr; // ポインタは v[1] を指す
*ptr = 34; // v[1] に 34 を代入
「++ptr」は、「ptr++」または「ptr += 1」と書いても同じだぞ
ポインタをインクリメントすることを「ポインタを進める」とも言うぞ。
「*ptr = 式; ++ptr;」は「*ptr++ = 式」と簡潔に書くこともできるぞ
- 「*ptr++」は「後置インクリメント」と言い、ptr の指す先を参照した後にポインタをインクリメントする
- 「*++ptr」という書き方もあり、これは ptr を先にインクリメントしてから ptr の指す先を参照するぞ
ポインタをデクリメント(-1)することで、前の要素に移動することも可能
下記はポインタを移動することで、配列要素を表示する例
const int SIZE = 10;
int v[SIZE];
int *ptr = &v[0]; // ptr は v[0] を指す
for(int i = 0; i < SIZE; ++i) {
std::cout << *ptr++ << "\n"; // ptr を進めながら、配列要素を表示
}
このように、ポインタは指している先を変更できるので、
異なるオブジェクトに対する処理をひとつのコードで記述することができて便利なんだぞ
下記の様に、ptr の値でループ終了を判断することも可能
const int SIZE = 10;
int v[SIZE];
for(int *ptr = &v[0]; ptr != &v[SIZE]; ++ptr) {
std::cout << *ptr << "\n"; // ptr を進めながら、配列要素を表示
}
この書き方の方が、余計なループ変数を使用しないのでバイナリがコンパクトかつ高速。
- 終了条件は ptr < &v[SIZE] でもよいが、!= の方が汎用的(後で出てくるイテレータにも使える)
- 単純なコンパイラであれば、この書き方の方がバイナリがコンパクトかつ高速だが、
最適化機能が高度な最近のコンパイラでは出力されるバイナリに違いが無いこともある
ポインタの値を変更しなくても、*(ptr+i) で i 先の要素を参照することも可能だぞ
const int SIZE = 10;
int v[SIZE];
int *ptr = &v[0]; // ptr は v[0] を指す
for(int i = 0; i < SIZE; ++i) {
std::cout << *(ptr+i) << "\n"; // ptr を進めず、配列要素を表示
}
編集問題:
- 配列へのポインタ ptr をfor文によりインクリメントすることで、配列 v[0]~v[9] を 0~9 で初期化しなさい
char v[10];
char *ptr = &v[0]; // ptr は v[0] を指す
// ここ以降に v[0] ~v[9] を初期化するコードを書きなさい
- 以下のコードを実行すると v[0] ~v[9] の値は何になるか予想し、実際に確認しなさい
char v[10] = {0}; // 要素を0で初期化
char *ptr = &v[0]; // ptr は v[0] を指す
*ptr++ = 1;
*ptr= 2;
ptr = &v[5]; // ptr は v[5] を指す
*++ptr = 3;
*ptr= 4;
自動スケーリング
- int 型データは4バイトの領域を占めるという話を覚えているだろうか?
- int v[10]; があった場合、&v[0] と &v[1] の差は4だったのを覚えているだろうか?
- 「int *ptr = &v[0]; ++ptr;」を実行した場合、ptr は v[1] を指すようになる。
- &v[1] は &v[0] よりも 4 大きいので、ptr の値も 4 大きくならなくてはいけない。
- ということは ptr を+1したのに、実際の ptr の値は 4 大きくなるといういうことだ。
- これを自動スケーリングと呼ぶ
演習問題:
- char, short, int, long long へのポインタを宣言・初期化し、インクリメントしたしたときに、値がいくつ増えるかを確認しなさい
前:ポインタの指す先を参照
|上:C/C++ ポインタ入門
|次:ポインタと配列