☜前の章へ 文字列の基本(初期化・代入・比較・連結・逆順)
☞次の章へ 構造体とは
ここではポインタの基本的な使い方について解説します。
この記事を読めば、ポインタの宣言方法や代入方法などが分かります。
ポインタとは
ポインタとは、変数のアドレスを格納するための変数のことです。
ポインタを理解できない、難しいと思う人は、ポインタのイメージが湧いていないと考えられます。そんな人にも分かりやすいように図を用いて解説します。
コンピュータは、メモリというデータを一時的に保存できる記憶領域を持っています。メモリは保存領域が細かく区切られており、変数を宣言すると、メモリに変数の保存場所が割り当てられます。
その保存場所をアドレスと言います。現実世界で例えると、住所のようなものです。
通常のint型変数xとポインタ変数ptrを例にした図を見てみましょう。
xには10が代入されており、ptrにはxのアドレスが保存されていると想定します。
変数xはメモリ上のアドレスである1番地に10を保存しますが、ptrはメモリ上のアドレスである5番地にxのアドレスである1番地を保存します。
今回は分かりやすいようにアドレスを1番地から5番地で区切りました。
このようにポインタ変数では直接値を保持するのではなく、アドレスを保持します。
ポインタの基本的な使い方
①ポインタ変数を宣言する方法
#include <stdio.h>
int main(void) {
//*をつけ、ポインタ変数を宣言
int *p_num;
return 0;
}
ポインタ変数を宣言するためには、変数名の前に*(アスタリスク)を付けます。
②ポインタ変数に変数のアドレスを代入する方法
#include <stdio.h>
int main(void) {
int num = 123;
//*をつけ、ポインタ変数を宣言
int *p_num;
//&をつけ、numのアドレスを代入
p_num = #
return 0;
}
ポインタ変数に通常の変数のアドレスを代入するためには、通常の変数名の前に&(アンパサンド)を付けます。
③ポインタ変数に格納されている変数のアドレス表示する方法
#include <stdio.h>
int main(void) {
int num = 123;
//*をつけ、ポインタ変数を宣言
int *p_num;
//&をつけ、numのアドレスを代入
p_num = #
//変換指定子%pを使い、ポインタ変数に格納されているアドレスを表示
printf("ポインタ変数に格納されているアドレス(変数numのアドレス) = %p\n", p_num);
return 0;
}
出力結果
ポインタ変数に格納されている変数のアドレスを表示するためには、printf関数の左側に変換指定子%pを書き、右側に*を除いたポインタ変数名を書きます。
④ポインタ変数に格納されている変数のアドレスに保存されている値を表示する方法
#include <stdio.h>
int main(void) {
int num = 123;
//*をつけ、ポインタ変数を宣言
int *p_num;
//&をつけ、numのアドレスを代入
p_num = #
//*をつけ、ポインタ変数に格納されているアドレスに保存されている値を表示
printf("ポインタ変数に格納されているアドレスに保存されている値(変数numの値) = %d\n", *p_num);
return 0;
}
出力結果
ポインタ変数に格納されている変数のアドレスに保存されている値を表示するためには、printf関数の左側に変換指定子%pdなどを書き、右側に*を含めたポインタ変数名を書きます。
⑤ポインタ変数に格納されている変数のアドレスに保存されている値上書きする方法
#include <stdio.h>
int main(void) {
int num = 123;
//*をつけ、ポインタ変数を宣言
int *p_num;
//&をつけ、numのアドレスを代入
p_num = #
//*をつけ、ポインタ変数に格納されているアドレスに保存されている値を表示
printf("ポインタ変数に格納されているアドレスに保存されている値(変数numの値) = %d\n", *p_num);
//*をつけるとアドレスに保存されている値を上書き出来る
*p_num = 456;
printf("変数numの値 = %d\n", num);
printf("ポインタ変数に格納されているアドレスに保存されている値(変数numの値) = %d\n", *p_num);
return 0;
}
出力結果
ポインタ変数に格納されている変数のアドレスに保存されている値上書きするには、*を含めたポインタ変数名に値を代入します。
⑥ポインタの基本的な使い方のまとめ
ポイント変数の扱い方
項目 | 記述例 |
ポインタ変数の宣言方法 | int *p_num; |
変数のアドレスをポインタ変数の代入する方法 | p_num = # |
ポインタ変数に代入されているアドレスの表示方法 | printf(“%p”, p_num); |
ポインタ変数に代入されているアドレスに保存されている値の表示方法 | printf(“%d”, *p_num); |
ポインタ変数を使い、アドレスの参照先の値を上書きする方法 | *p_num = 456; |
これまで解説してきた、ポインタの基本的な使い方を表にしてまとめています。
パット見て分かるようになっているので、ポインタを使用する際の参考にしてください。
ポインタの関数での基本的な使い方
関数の引数でポインタを受け渡す方法とメリット
グローバル変数とローカル変数について学習した際に、ローカル変数は宣言された関数内でしか使えないと学びました。
しかし、アドレスを介すことで、異なる関数間でデータの共有や変更が可能になります。
#include <stdio.h>
// 関数の引数にポインタを使用し、そのポインタを通じて変数の値を変更する関数
void changeValue(int *ptr) {
*ptr = 789; // ポインタを通じて変数の値を変更
}
int main(void) {
int num = 123;
printf("変更前の値: %d\n", num);
// 関数にポインタを渡して変数の値を変更
changeValue(&num);
printf("変更後の値: %d\n", num);
return 0;
}
このソースコードを実行してみると以下のように出力されます。
このように異なる関数間で変数を操作することが可能になります。
関数の戻り値でも変更は可能ですが、基本的に戻り値は1つしか返せません。関数の引数には複数のポインタを渡すことができるため一度に複数の操作が可能になります。
また、引数を渡すだけでなので、戻り値で発生するメモリの使用を抑えることができ、メモリ効率の観点からもメリットがあります。
練習問題
#include <stdio.h>
int main() {
// int型のポインタ変数p_tempを宣言
int *p_temp;
return 0;
}
#include <stdio.h>
int main() {
// int型の変数tempを宣言
int temp = 42;
// int型のポインタ変数p_tempを宣言し、tempのアドレスを設定
int *p_temp = &temp;
return 0;
}
#include <stdio.h>
int main() {
// int型の変数tempを宣言
int temp = 42;
// int型のポインタ変数p_tempを宣言し、tempのアドレスを設定
int *p_temp = &temp;
// p_tempが指すメモリの値を表示
printf("p_tempが指すメモリの値: %d\n", *p_temp);
return 0;
}
#include <stdio.h>
int main() {
// int型の変数tempを宣言
int temp = 42;
// int型のポインタ変数p_tempを宣言し、tempのアドレスを設定
int *p_temp = &temp;
// p_tempを通じてtempに値を代入
*p_temp = 20;
// p_tempが指すメモリの値を表示
printf("p_tempが指すメモリの値: %d\n", *p_temp);
return 0;
}