徹底図解!C言語ポインタを初心者向けに分かりやすく解説

ポインタ解説ページのアイキャッチ

C言語学習において最も躓きやすいと言われているのがポインタです。

私も最初ポインタを学んだ時はポインタが理解出来ず、また使う理由も分からなかったので出来るだけ避けてプログラミングをしていました。しかし、今ではポインタをすっかり使いこなせるようになってます。ポインタなしのC言語プログラミングは考えられないです。

ポインタ学習で躓きやすい理由は下記の3つだと思います。

ポインタ学習につまづきやすい理由
  • ポインタのイメージができていない
  • そもそもポインタを使うメリットが分からないのでポインタを使わない
  • ポインタを身につけるための勉強方法がわからない

このページでは上記の3つを解決できるように、ポインタの概念から説明し、ポインタの使い方・ポインタを使うメリット・ポインタの学習方法について、わかりやすく説明したいと思います。

ポインタとは

ポインタを理解するコツ、これは文章ではなく図で理解することです。なので文章だけでなく図を使って説明していきます。

ポインタはアドレスを格納する変数

ポインタとは「アドレスを格納する変数」です。実際にポインタ変数に格納されているのは数字ですが、ポインタ変数に格納された数字はアドレスとして扱うことができます。

アドレスとはメモリ上の位置を示すものです。アドレスと言う名の通りメモリ上の住所みたいなものです。

例えばC言語では変数宣言を行うと、プログラム実行時に変数宣言の型に応じたサイズのメモリが確保され、メモリ空間のどこかに配置されます。下の図では変数 A 用に4バイトのメモリが確保されて 0xAA 番地とい位置に配置され、変数 B 用に4バイトのメモリが確保されて 0xBB 番地という位置に配置された例を示しています(図の四角一つが一バイトを表現していると考えてください)。この 0xAA 番地、0xBB 番地のようなメモリ上の位置をアドレスと呼びます。

変数がメモリ空間上に確保される様子

また、メモリの確保とは「一時的にメモリの一部分を自分のプログラム専用のメモリにしてしまうこと」です。OS(Windows や Mac など)に自分のプログラムでメモリを使わせてくださいとお願いすることでメモリを確保することができます。確保されたメモリは自分のプログラムで自由に使うことが可能ですし、基本的に他のアプリなどのプログラムからアクセスされることはありません。

そして、その確保したメモリが配置されているアドレス(位置)を覚えておくのがポインタです。ちなみにアドレスは16進数で表現することが多いのでこのページでもアドレスは全て16進数で表記しています。

このメモリ上に変数用のメモリが確保される様子やポインタの動きをプログラムの流れと一緒に見ていきましょう!

まず int 型とポインタの変数宣言をします。

int valueX;
int valueY;
int *ptr;

前述の通り変数宣言すればメモリが確保されメモリ空間上に配置されます。

int 型のサイズは基本的に4バイトなので、valueX と valueY の変数宣言により、4バイト分のメモリが2つ分確保されることになります。さらにポインタの変数宣言でも同様にその変数用のメモリがメモリ空間上に配置されます。ポインタのサイズは 32bit PC の場合は4バイト、64bit PC の場合は8バイトになります。

ポインターもメモリ空間上に配置される様子

変数 valueX と変数 valueY に値を格納してみましょう。

valueX = 100;
valueY = 200;

メモリ上では下記のように変わり、valueX と valueY 用のメモリに値が格納されることになります。

メモリに値が格納される様子

続いてポインタ ptr に valueX のアドレスを格納してみましょう。変数名の前に「&」記号をつければその変数のアドレスを取得することが可能です。「&」はアドレス演算子と呼びます。

ptr = &valueX;

これにより、下の図のように、ptr に「valueXのアドレス」が格納されることになります。

ポインタにvalueAのアドレスが格納される様子

これを「ポインタ ptr が valueX を指す」という言い方をします。

続いて ptr を表示してみましょう!int 変数などと同様に、printf 関数でポインタの値を表示することができます。書式指定子には “%p” を用います。

printf("%p¥n", ptr);

表示結果は下記のようになります。

0x7ffeedfbeaf8

わけのわからない文字列になりますが、これが valueX 変数のアドレスになります。でもこの数字だけだとポインタのイメージが湧きにくいですね…。

ポインタのイメージは矢印

ただし、はっきり言ってこのアドレスの数字自体は全く意識する必要はありません!特にプログラミング入門者の方は意識することは不要です(ハードを制御するようなデバイスドライバ等を作成する場合に意識する必要が出てきます)。

ポインタで重要なのは「何を(どこを)指しているか」です。アドレスの値そのものではありません。

ポインタには前述の通り他のメモリ空間のアドレスが格納されていますが、アドレスが格納されているということは、そのポインタがそのアドレスを指しているということになります。例えば先ほどのプログラムの例では ptr は valueX という変数のアドレスを指していることになります。

ですので、先ほど表示したようなアドレスの値よりも、ポインタが何を指しているかを考えた方が良いです。これを考えるときのコツはポインタをメモリ空間上の矢印でイメージすることです。

ポインタにはアドレスが格納され、メモリ空間上のどこかを指しているわけですから、ポインタからどこかに矢印が伸びてるイメージを描いてみましょう!

例えば先ほどのプログラムではポインタ ptr には valueX のアドレスが格納される、つまり ptr が valueX のアドレスを指しているということですので下のように図を書くことができます。

ポインタがvalueAを指す様子

要はポインタとはこの矢印ですわけのわからないアドレスの値で考えるよりもこの矢印でイメージする方が直感的にポインタの動きを確認することができるようになります。

今度はポインタptrに valueY のアドレスを格納することを考えてみましょう。

ptr = &valueY;

これにより ptr から伸びる矢印が valueY を指すようになります。

ポインタがvalueBを指す様子

つまり、ptrに値を代入するということは「ptr から伸びる矢印の先(アドレス)が変わるということ」となります。

さらに、「*」を用いる事で、このポインタの指す先のメモリアクセスすることができ、値の取得や代入を行うことが可能です。「*」は間接演算子と呼ばれます。

例えば下記のように値を参照するだけでなく、

printf("%d¥n", *ptr);

下記のようにポインタの指す先を直接変更することも可能です。

*ptr = 500;

ptr は valueY を指していますので、上記により valueY に “500” が格納される事になります。

このようにポインタを用いれば他の変数を指すだけでなく、「*」を用いることで、ポインタの指す先のメモリ(変数を指しているのであれば変数そのもの)に格納されている値にアクセスすることが可能です。

ポインタから他の変数の値にアクセスする様子

ポインタの基本的な使い方

ここまでのおさらいの意味も含めてポインタの基本的な使い方を解説していきます。

ポインタの変数宣言をする

ポインタ変数は、変数の型として int や char などの基本的な変数の型の後ろに「*」を付けて変数宣言します。

int *int_ptr;
char* char_ptr;

「*」は変数名側につけても良いですし、型側につけても良いです。

int 型や char 型など、変数は型に応じてサイズが異なりますが、ポインタの場合はどの型で宣言しても同じサイズです。

ただしコンパイルする環境によってサイズが異なります。32 bit PC の場合は4バイト、64 bit PC の場合は8バイトのサイズになるはずです。

また、基本的に変数宣言時に使用した型と同じ型の変数を指すポインタとして使用します。例えば上記の int_ptr であれば int 型の変数、char_ptr であれば char 型の変数を指すポインタとして使用します。

ただし、実は異なる型の変数を指させることも可能です。この辺りは下のページでポインタの型による違いに絡めて解説していますので、興味がある方はこのページを読み終わった後にでも読んでみてください。

ポインタの型の解説ページのアイキャッチC言語のポインタの型の意味は?

ポインタの指す先を変更する(アドレスを格納する)

ポインタにはアドレスを格納することが可能です。前述した通り、ポインタにアドレスを格納するということは、ポインタにどこかを指させるということになります。

変数を指す

変数のアドレスを格納するためには下記のように変数名の前に「&」を付けて記述します。

int x = 100;
int *ptr;
ptr = &x;

他のポインタと同じアドレスを指す

他のポインタと同じアドレスを指させたい場合は下記のように記述します。ポインタにはアドレスが格納されていますので「&」は不要です。

int x = 100;
int *ptr1;
int *ptr2;
ptr1 = &x;
ptr2 = ptr1;

下の図のように2つの矢印が同じ場所を指すことになります。

2つのポインタが同じ変数を指している様子

配列の先頭を指す

また配列のアドレスを格納することも可能です。配列のアドレスを格納する方法は2つあります。2つとも同じアドレスがポインタに格納されることになります。

1つ目はポインタに配列名を代入することです。

char arr[5] = {1, 2, 3, 4, 5};
char *ptr;
ptr = arr;

C言語の場合、配列名は配列の先頭アドレスを(便宜的に)表すようになっていますので、上記の記述でポインタに配列の先頭アドレスを指させることが可能です。

2つ目はポインタに配列の先頭([0] 要素)のアドレスを代入することです。

char arr[5] = {1, 2, 3, 4, 5};
char *ptr;
ptr = &(arr[0]);

2つの方法で書き方は異なりますが、両方とも配列の先頭をポインタが指すことになります。

ポインタが配列の先頭を指す様子

配列の途中の要素を指す

配列の場合、配列の途中の要素をポインタに指させることも可能です。

char arr[5] = {1, 2, 3, 4, 5};
char *ptr;
ptr = &(arr[3]);

この記述の場合は下の図のように arr 配列の第 3 要素(arr[3])をポインタが指すことになります。

ポインタが配列の途中要素を指す様子

ポインタの指すメモリの値にアクセスする

続いてポインタの指すアドレスのメモリの値にアクセスする方法について解説していきます。

ポインタの指す先のメモリに格納されている値にアクセスするためにはポインタ変数の前に「*」を付けます。

int x = 100;
int *ptr;
ptr = &x;
*ptr = 200;

ポインタが配列を指している場合は下記のように配列と同じようにインデックスを指定して各要素の値にアクセスすることが可能です。

char arr[5] = {1, 2, 3, 4, 5};
char *ptr;
int i;

ptr = arr;
ptr[0] = 60;
ptr[3] = 90;

またアドレスの値を変更することで、配列の各要素にアクセスすることも可能です。

char arr[5] = {1, 2, 3, 4, 5};
char *ptr;
int i;

ptr = arr;
*ptr = 60;
*(ptr + 3) = 90;

これらは配列データ用のメモリがメモリ空間上で連続しているために可能な操作になります。

例えば配列 arr の先頭アドレスを便宜的に 0xA0 とすると、arr[0] のアドレスは 0xA0、arr[1] は 0xA1、arr[2] は 0xA2・・・という風に、配列の各要素はアドレス的に連続してメモリ上に確保されることになります。

配列の各要素が連続でメモリ上人存在する様子

ですので、ポインタに +1 してやれば arr[1] に、+2 にしてやれば arr[2] に、という感じでアドレスの値を自分で変更して配列のメモリにアクセスすることが可能です。

ただし、通常の配列通りに配列のサイズを超える位置にアクセスしてしまうとメモリアクセスエラーとなりますので注意しましょう。

また、ポインタに +1 した場合、アドレスの値がいくつ増えるかはポインタの型(char* や int* など)によって異なります。この辺りは下のページで解説していますので、気になる方はこのページを読み終わった後にでも読んでみてください。

ポインタの型の解説ページのアイキャッチC言語のポインタの型の意味は?

malloc で動的に確保したメモリのアドレスを指す

ポインタが指すことの出来るのは変数のみではありません。プログラム内でメモリを明示的・動的に確保して、それを指すことも可能です。この辺りを知っていれば、ポインタのイメージがさらに湧きやすくなります。

動的にメモリを確保する malloc 関数

このメモリを動的に確保するために使用する関数は malloc 関数です。

malloc関数

#include <stdlib.h>

void* malloc(size_t size)

malloc 関数とは、要求されたサイズ(sizeバイト)分のメモリを動的に確保する関数です。

「動的に」というところがミソで、実行時に必要なメモリ量が変わるようなプログラムでも、malloc 関数を使えばその必要な量のメモリのみを確保することが可能です(配列だとプログラミング時に決めたサイズから変更することができません)。

ですので特に省メモリを意識したC言語プログラムを作成するのに便利な関数です。

malloc 関数の使い方

malloc 変数は引数に確保したいメモリのサイズ(バイト数)を指定して実行します。例えば下記を実行すれば、malloc 関数により 6 バイト分の連続メモリを確保することが可能です。

malloc(6);

メモリを動的に確保する様子

確保されたメモリは変数宣言で確保したメモリ同様にプログラム中で自由に扱うことが可能です。ですが…、変数宣言で確保したメモリとは異なり、動的確保したメモリには変数名がついていません。ですので変数名を使ってこのメモリにアクセスすることは不可能です。

ポインタで malloc で確保したメモリを指す

そこで使用するのがポインタです。ポインタで動的確保したメモリの位置を指しておき、ポインタを使って動的確保したメモリを使用します。

下記のように記述することで malloc 関数で動的確保したメモリをポインタで指すことができます。

char *ptr;
ptr = (char*)malloc(6);

そしてこのポインタを使用して動的確保したメモリを自由に扱うことが可能になります。

ポインタが動的確保されたメモリを指す様子

malloc 関数で確保したメモリへのアクセス

malloc 関数で確保したメモリは連続的につながったメモリとなります。例えば malloc 関数で指定したサイズが 16 バイトで、malloc 関数の返却値(確保したメモリの先頭アドレス)が 0xA0 なのであれば、確保したメモリは 0xA0 から 0xAF に存在するものとなります。

そのため、アドレスのメモリに格納されている値にアクセスするで解説したように下記のようにインデックスを指定する、ポインタの値を加算することで確保したメモリの様々な部分にアクセスすることが可能です。

char *ptr;
int i;

ptr = (char*)malloc(6);

for(i = 0; i < 6; i++){
    *(ptr + i) = i * 10;
}

for(i = 0; i < 6; i++){
    printf("%d : %d\n", i, ptr[i]);
}

動的確保したメモリは解放処理が必要

動的確保したメモリは使用が終わったら解放する必要があります。このメモリの解放を行うことで、他のプログラムがこのメモリを使用することが可能になります。

この解放を行うのは free 関数で、引数には動的確保したメモリの先頭アドレスを指定します。

free(ptr);

解放しないと他のプログラムがそのメモリを使用できないだけでなく、定期的にメモリを確保するようなプログラムが長時間稼働すると、途中でメモリを確保できなくなってプログラムが動けなくなる場合もあります。

動的確保したメモリはしっかり解放する癖を付けておくと良いと思います。

必要になったらメモリを動的確保し、不要になったらメモリを解放する、これを繰り返すことで、省メモリなプログラムが作成できます。

関数を指す

ちょっと上級者向けですが、ポインタではプログラム内の関数を指すことも可能です。関数を指すポインタを関数ポインタと呼びます。関数ポインタを構造体のメンバに関数を用いることでクラス(のようなもの)をC言語で実現することもできます。

関数ポインタについては下のページで解説していますので、興味のある方はこのページを読み終わった後にでも見てみてください。

福引結果中間報告!(2018夏)福引結果中間報告!(2018夏)

ポインタを学び始めた方であれば、関数もポインタで指すこと可能であることを頭の片隅に置いておくくらいで良いと思います(プログラムの規模が大きくなったり並列処理プログラミングなどを実装しだすと、この関数ポインタが活躍します)。

NULL を指す

ポインタを扱うことで非常に重要な意味合いを持つものが NULL です。NULL とは「何もない空の状態」みたいな意味ですが、C言語のポインタにおいては下記の2つの意味で主に使用されます。

  • どこも指していない状態
  • 関数エラー時の戻り値

どこも指していない状態

変数は変数宣言された直後だと不定値(どんな値か分からない値)が格納されています。これはポインタにおいても同様です。ポインタはメモリ空間上を指すものですので、変数宣言直後はどこを指しているか分からない状態です。

この状態でポインタの指す先にアクセスしようとすると、メモリアクセスエラーが発生し、プログラムが落ちて即終了する危険な状態です。

これを防ぐために NULL を用います。まだどこも指していない状態の時にはポインタに NULL を指させておけば、ポインタが NULL の場合はポインタの指す先へのアクセスを行わないように制御することでメモリアクセスエラーを防ぐことが可能です。

int *ptr;
ptr = NULL;

/* いろんな処理 */

if(ptr == NULL){
    printf("*ptr = %d\n", *ptr);
}

関数エラー時の戻り値

戻り値がポインタである関数の場合、エラー時の戻り値を NULL としている関数が非常に多いです。ですので、このような関数実行時にエラーが発生したかどうかは、実行後に戻り値が NULL であるかどうかを調べることにより確認することが可能です。

int *ptr;
ptr = (int*)malloc(100 * 1024 * 1024 * 1024);
if(ptr == NULL){
    /* エラー処理 */
}

例えば前述の malloc 関数もメモリが足りない等でエラーとなる場合は NULL が返却されます。エラーの場合は戻り値を格納した ptr を使用してメモリアクセスするとメモリアクセスエラーとなってしまいます。これを防ぐために戻り値が NULL であるかどうかを判断し、NULL である場合はエラー終了する・メモリ確保できるようになるまで待つような処理を行いましょう。

スポンサーリンク

ポインタのメリット

ポインタを使用する主なメリットは下記の3つです。

  • できることが増える
  • 高速化できる
  • 省メモリ化できる

特に重要なのは「高速化できる」と「省メモリ化できる」です。

現在数あるプログラミング言語がある中で、いまだにC言語が使用される理由は高速であること省メモリであることです。読みやすい・書きやすいプログラミング言語は他にもいくらでもありますが、この2つの強みがあるので、いかに安く性能の良いものを出すかが重要である組み込み製品でC言語はいまだに広く利用されています。

そしてこの2つの強みを実現しているのがポインタなんです。C言語で実装する最大の理由は高速で省メモリであることですので、この2つの強みを活かせるばポインタの利用は、C言語においては必須であると考えて良いです。

それではこのポインタを用いるメリットと、なぜこのようなメリットがあるのかを1つ1つ見ていきましょう!ここをしっかり理解することが、ポインタ理解への近道です。

できることが増える

ポインタを使うことでC言語で実現できることがグッと増えます。というか、ポインタが使えないとかなり不便です。

具体的には自分で作れる関数の幅が広がります。例えば下記のプログラムについて考えてみましょう。

#include <stdio.h>
 
void func(int x, int y){
    int tmp;
    tmp = x;
    x = y;
    y = tmp;
}

int main(void){
    int valueX;
    int valueY;

    valueX = 100;
    valueY = 200;

    func(valueX, valueY);

    printf("valueX = %d, valueY = %d\n",
        valueX, valueY);

    return 0;

}

実行結果は下記となります。

valueX = 100, valueY = 200

func 関数に valueX と valueY を引数として渡し、関数内で値を入れ替えたはずなのにそれが反映されてません。

これは、C言語における関数呼び出しでは、引数で指定された変数はその変数そのものではなく、その変数を複製したものを関数側に渡すようになっていることが原因です。つまり、関数内では引数で渡されたデータではなく、複製されたデータを用いて処理が行われます。

関数呼び出し時に変数が複製される様子

ですので、いくら関数の中で引数のデータの値を変更したところで呼び出し側の変数の値には影響しません。処理した結果を呼び出し側に渡したいのであれば return で戻り値として渡す必要があります。ただし、戻り値で渡せるデータは一つなので、関数が呼び出し側に渡せる結果は一つのデータのみとなってしまいます。

これを解決するのがポインタです。次は下記のプログラムについて考えてみましょう。

#include <stdio.h>
  
void func(int *x, int *y){
    int tmp;
    tmp = *x;
    *x = *y;
    *y = tmp;
}

int main(void){
    int valueX;
    int valueY;
    int *ptrX;
    int *ptrY;

    valueX = 100;
    valueY = 200;
    ptrX = &valueX;
    ptrY = &valueY;

    func(ptrX, ptrY);

    printf("valueX = %d, valueY = %d\n",
        valueX, valueY);

    return 0;

}

こちらの結果は下記の通りです。

valueX = 200, valueY = 100

しっかり関数実行により値が入れ替わっていますね!

前述の通り関数は実行時に引数として渡されたデータの複製が作成されます。これは引数がポインタの時でも全く同じです。ただしポインタの場合はポインタに格納されたアドレスが複製されることになります。

したがって、関数呼び出しにより複製されたポインタも複製元のポインタが指している場所を同様に指すことになります。具体的には、上のプログラムで言うと func 関数の引数 x と y は元々 ptrX と ptrY が指していた valueX と valueY をそれぞれ指すことになります。

関数実行時にポインタが複製される様子

したがって func 関数内でも「*」を用いて valueX と valueY にアクセスすることができ、その値を変更することが可能です。上記プログラムでは func 関数内で *x と *y に値を代入することで valueX と valueY の2つの値を変更することができます。

ポインタを利用することで、呼び出し側に関数内での処理結果を複数渡すことができるようになったところがポイントです(ポインタを使わないと渡せるのは戻り値の一つのみ)。

このようにポインタを使用することで自分作成できる関数の幅が広がります。

関数をわざわざ作らなければ

ポインタは不要じゃん!

と言う声もあるかもしれません。しかし、関数は必要に応じて作成した方が、ソースコードは読みやすくなります。ソースコードの規模が大きくなれば大きくなるほどこの読みやすさは重要になっていきますので、特に製品向けの大規模なC言語プログラムを作成するような場合は、必要に応じて関数を作成すること、そして必要に応じてポインタを利用することを心がけた方が良いです。

高速化ができる

ポインタを使用することでプログラムの高速化を行うことが可能です。下記は funcA と funcB をそれぞれ10億回繰り返し呼び出した時の処理時間を表示するプログラムです。funcA と funcB は両方とも何も処理をしない関数なので単純に呼び出し時間を表示することになります。

#include <stdio.h>
#include <time.h>

#define N 1000000000

struct data {
    double d1;
    double d2;
    double d3;
    double d4;
    double d5;
    double d6;
    double d7;
    double d8;
    double d9;
    double d10;
};

void funcA(struct data d){
}

void funcB(struct data *d){
}

int main(void){
    long long i;
    struct data d;
    clock_t start, end;

    start = clock();
    for(i = 0; i < N; i++){
        funcA(d);
    }
    end = clock();
    printf("funcA:%.3f[sec]\n",
        ((double)end - (double)start) / CLOCKS_PER_SEC);

    start = clock();
    for(i = 0; i < N; i++){
        funcB(&d);
    }
    end = clock();
    printf("funcB:%.3f[sec]\n",
        ((double)end - (double)start) / CLOCKS_PER_SEC);

    return 0;

}

実行結果は下記のようになりました。

funcA:11.689[sec]
funcB:2.678[sec]

両方とも空の関数を呼び出しているだけですが、処理時間に大きな差が出ています。この差はできることが増えるで前述した関数実行時のデータの複製により発生しています。

funcA では引数が data 構造体そのものなので data 構造体がまるまる(80 バイト分)複製されますが、funcB では引数がポインタですので、ポインタのみ(32 bit PC であれば 8 バイト分)が複製されます。サイズが大きいほど複製にも時間がかかるため、構造体そのものをまるまる複製する funcA の方が時間がかかっています。

構造体がコピーされる様子

今回は関数呼び出しに注目しましたが、関数呼び出し時以外でも大きなデータを扱う時はコピーが発生すると時間がかかってしまいます。例えが大きなサイズの画像データなどは画像データそのものをコピーすると処理時間が長くなってしまいます。しかしそれをポインタで指す先を設定するだけで処理できるのであれば一瞬で処理を完了させることが可能です。

ポインタコピーと画像コピーの違い1

このようにポインタを使えばデータのコピー時間を短縮することができ、これによりプログラムの高速化を行うことが可能です。

省メモリ化ができる

先ほど解説した高速化できるでも解説したようにデータそのものをコピーすると、元々あったコピー元のデータのメモリ+コピー先のデータのメモリが必要になりますので、元々のデータに対して2倍のサイズのメモリが必要になってしまいます。

ポインタを扱えばコピー自体を減らす、コピーするデータのサイズを減らすといったことが可能でありプログラム実行に必要なメモリを削減することが可能です。

ポインタコピーと画像コピーの違い2

また malloc 関数による動的なメモリ確保を行うことで、動的なメモリ確保を行うことで必要になった時に必要な分だけメモリを確保するような動きが実現可能になります。

ポインタの勉強方法

ポインタをしっかり使いこなすための勉強方法として一番オススメなのが「リスト構造のプログラミング」です。

リスト構造はデータをリスト上に繋ぎ合わせて管理するデータ構造です。この繋ぎ合わせはまさにポインタで他のデータを指す操作になります。ですので、非常にポインタを矢印としてイメージしやすいです。そのためリスト構造はポインタを身につけるにはうってつけの題材だと思います。

リスト構造でデータをつなぐ様子

またリスト構造では、データが追加された時はメモリの動的確保を、データが削除された時はメモリの解放とデータの繋ぎ合わせをそれぞれ行う必要があるため、ポインタを使用する箇所が大変多いです。多い分、ポインタに慣れることができると思います。

リスト構造でデータを動的確保で追加する様子

リスト構造については下記ページで解説していますので、ポインタを身に付けたいと思っている方は是非読んでみてください。

リスト構造をC言語プログラムの実例を用いて解説

まとめ

  • ポインタは概念さえ理解すれば難しくない
  • 文章の説明よりも図の方がイメージしやすい
  • ポインタを使うことで作成できる関数の幅が広がり、省メモリ・高速なプログラムが作成可能
  • ポインタを身につけるにはリスト構造が最適

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です