📕

C言語のポインタについて

2025/01/19に公開

こんにちは。ねこがくれです。
今日は、C言語の中でもつまづきやすい「ポインタ」について、誰でもわかりやすく説明してみようと思います。
ポインタを理解することで、C言語がもっと便利になるので、一緒に勉強していきましょう。(というかポインタを理解しないことには何もできないです)

そもそもポインタって何ぞ?

まず、ポインタは「変数のアドレスを記憶する変数」です。
…と書くと難しそうに感じるかもしれません(実際難しいです。少しだけ)が、簡単に言えば「データの入ってるロッカー番号を保管する変数」です。

たとえば、次のコードを見てください:

ptr.c
int ptr_target = 8;  // 数値8を持つ変数
int* ptr = &ptr_target;  // ptr_targetのアドレスをポインタptrに格納

ここで、注目するべきはint* ptr = &ptr_target;です。順に見ていきます。
まず、int* ptrでint型に付随するポインタ変数を宣言しています。
「付随する」と書きましたが、ポインタ型は何らかの型から派生しないと存在できない型だからです。(たとえば、int型のポインタ、bool型のポインタなど)

そして、ptr = &ptr_target;で先ほど宣言したポインタ変数ptrに変数ptr_targetのメモリ上のアドレスを代入しています。&演算子でその変数のアドレスを知ることができます。

じゃあ、ポインタを使うと何が便利なの?

例えば、関数にデータを渡すとき、普通は引数に「値をコピー」して渡します。でも、大きなデータをコピーすると時間もメモリもたくさん使いますよね。(たとえば数GBのファイルをフォルダからフォルダにコピーするときに時間かかりますよね。そういうことです。)

ですがポインタを使えば、コピーせずにデータそのものを操作できるので、とても効率的にデータを渡すことができます。

以下は、ポインタを使って値を変更する例です:

ptr_change.c
#include <stdio.h>

void changeValue(int* ptr) {
    *ptr = 100;  // ポインタが指す場所に100を代入
}

int main() {
    int ptr_target = 42;
    printf("変更前のptr_target: %d\n", ptr_target);

    changeValue(&ptr_target);  // ptr_targetのアドレスを渡す

    printf("変更後のptr_target: %d\n", ptr_target);

    return 0;
}

このコードを実行すると、

変更前のptr_target:42
変更後のptr_target:100

と出力されます。ポインタを介して変更できましたね。
詳しい説明行きます。
まずptr_targetを宣言し、changeValue関数に自分自身のアドレスを渡しています。
そしてchangeValue関数で直接ptr_targetの値を変更しています。
ポインタを使うと、こんなふうに「他の関数から値を変える」ことが簡単に実装できます。

ポインタの怖いところ

ただ、便利なポインタにも注意点があります。一番多いのは、プログラムが「Segmentation Fault(メモリエラー)」を起こして止まってしまうこと。
特に次のような点には注意してください:

  1. 初期化されていないポインタを使わない
    宣言だけして値を入れないポインタ(野良ポインタ)は危険!

  2. NULLポインタをチェックする
    ポインタがNULLかどうか確認せずに使うとエラーになります。(私も2、3年書いてますが今でもやってしまいます)

  3. 解放済みのメモリにアクセスしない
    free()で解放したメモリにアクセスしないように気をつけましょう。

最後に

ポインタは最初は難しく感じるかもしれませんが、一度慣れるとC言語のプログラムがぐっと書きやすくなります。(理解してから私もC楽しい!って子供ながらになってます。)

私も最初はとても苦労しましたが、たくさんコードを書いて試すことで少しずつ理解できるようになりました!
ぜひこの記事を読んで「ポインタちょっとわかったかも!」と思ってもらえたら嬉しいです。

最後まで読んでくださりありがとうございました!
それではまた次回の記事でお会いしましょう!

Discussion