この記事について
C言語基礎 第11回では、C言語のポインターという機能について説明していきます。ポインターは注意して利用しないとバグなどの問題が発生する可能性があります。しかし、ポインタはパフォーマンス向上やプログラムの柔軟性を提供するため、重要な概念です。よく理解して、使いこなせるようになりましょう。
ポインターとは
ポインターとは「変数名を使わずに、メモリ上の住所(アドレス)でデータの操作をする機能」です。今までは変数に格納された値を操作する際に、その識別子(変数名)を使用していましたが、ポインターを使うと変数名を使用せずに操作することが可能になります。ポインターは変数の一種で、メモリアドレスという特殊な値が格納されます。メモリのアドレスとは、コンピュータのメモリ上にデータが格納されている位置を識別するための一意の番号のようなものです。
メモリアドレス
プログラムが実行される際、変数や配列もメモリに記憶しながら処理が進んでいきます。つまり、変数や並列もメモリのどこに記憶されているかを簡単に調べることが可能です。具体的な使い方を確認していきましょう。
#include <stdio.h>
int main(void){
int num = 5;
int v[] = {1,2,3,4,5};
printf("変数numのアドレスは%pです。\n", &num);
printf("配列vのアドレスは%pです。\n", v);
return 0;
}
アドレスを調べる際にはアドレス演算子の”&”を使用します。以下の2点に注意しましょう。
- 配列は配列名だけで先頭のアドレスを返す
- アドレスのフォーマット指定子は’%p’
次にポインターの使い方について確認していきましょう。ポインターとはメモリアドレスを格納する変数でした。ポインター変数と呼ぶくらいなので、基本的な使い方は変数とほとんど同じと思ってよいです。とはいえ、いくつか違いがありますので以下で確認していきましょう。
#include <stdio.h>
int main() {
int num = 42;
int *ptr;
ptr = #
return 0;
}
ポインタ変数を宣言する際には「これは通常の変数ではなく、ポインター変数である」と明示する必要があるので変数名の前に’*'(アスタリスク)を付けます。ポインター変数ptrを宣言し、初期値として「&num」を指定します。これにより、ポインター変数ptrは&num、つまり変数numのアドレスで初期化されます。
変数ptrの型を「intへのポインター」といいます。「このポインターの指し示す先にint型のデータがある」という意味になります。原則として、ポインターの指し示す場所のデータ型によってポインター変数の型も変えなくてはならないことに注意しましょう。
間接参照
それでは次に、変数名を使わずメモリ上の住所(アドレス)でデータを出力する方法を確認しましょう。以下のprintf関数に注目してください。
#include <stdio.h>
int main(void){
int num = 42;
int *ptr;
ptr = #
printf("ptrが指す先の値: %d\n", *ptr);
printf("ptrに格納されている値:%p\n",ptr);
*ptr = 30;
printf("ptrの参照先の値を書き換えました。%d", *ptr);
return 0;
}
最初のprintf関数ではptrの前に’*’がついていることがわかります。この’*’はポインター変数宣言時の’*’とは違う意味を持ち、「ポインター変数の指し示す先のデータを参照する」という意味があります。このことを間接参照と呼び’*’のことを間接参照演算子と呼びます。変数numという識別子を使わずに’42’という値が参照できていることが確認できます。ここで2つの’*’の違いをおさらいしましょう。
- ポインター変数宣言時の’*’はポインターであることを意味している
- ポインターの中身を調べるときに使う’*’は間接参照演算子
ポインター変数は’*’を付けると間接参照しますので、変数と同じように値を書き換えるというような処理もできます。
配列とポインター
C言語では、ポインターを利用して配列の要素にアクセスすることができます。配列は配列名だけでその先頭のアドレスを返しますので、ポインターを使えば配列の要素に効率的にアクセスできます。具体的にプログラムを確認していきましょう。
#include <stdio.h>
int main(void)
{
int numbers[] = {1, 2, 3, 4, 5};
int *ptr;
ptr = numbers;
printf("配列のインデックス0番目の値を表示:%d\n",numbers[0]);
printf("ポインターを使った配列の操作:%d\n",ptr[0]);
return 0;
}
上のコードは配列を用意し、ポインターを使って配列にアクセスするプログラムです。配列は配列名のみで先頭のアドレスを格納しますので、ポインター変数ptrにはそのまま配列名を格納することに注意しましょう。また、ポインター変数ptrと配列名numbersには同じ値が格納されていますので、配列のインデックス指定と同じようにポインター変数を利用できる点も確認しましょう。
まとめ
今回はC言語のポインターの使い方について紹介しました。C言語は普段使っているパソコンのようなメモリ容量の大きい環境でももちろん使用されますが、リモコンのような要領の限られた環境でも非常によく開発されています。つまり、そのかぎっれたメモリをいかに無駄なく使うかが非常に重要になってきます。ポインターをよく理解し、無駄のないプログラムを作成するよう心がけていきましょう。
コメント