シェアする

  • このエントリーをはてなブックマークに追加

C言語 ポインタが理解できない理由 – 関数とポインタ

シェアする

  • このエントリーをはてなブックマークに追加
  • 1

C言語 ポインタが理解できない理由 – 関数とポインタ

こんにちは、じゅんです。

c_pointer_mindmap  

昨日までで1章と2章を説明しましたが、今日はいきなり飛んで第7章を説明したいと思います。

ポインタを最も使う場面、それは引数

参考書として挙げている『C言語 ポインタが理解できない理由』では終盤の章割りになっていますが、ここではいきなり『関数』について説明したいと思います。

    1. プログラム
    2. メモリの使われ方
    3. 型とポインタ
    4. 配列とポインタ
    5. 文字列とポインタ
    6. mallocとポインタ
    7. 関数とポインタ
    8. 構造体とポインタ

ポインタを勉強する際に、ただ概念だけを覚えようとしてもいざ実際に使おうと思ってもなかなかどういう風に使って良いのか悩んでしまうでしょう。

実際にポインタというのはこういう場面で使うんだよ、というのを想定して勉強した方が使えるようになるのも早いです。

で、もっともよくポインタが使われる場面として、『引数のポインタ渡し』があります。

通常、関数というのは’return’文によって値を1つだけ返すことができるようになっています。

実際にはこれでError Codeを返すことが多いと思います。

では、関数間で変数のやり取りをしたい場合はどうすれば良いのか?

通常のいわゆる引数の『値渡し』という方法でやり取りをしても、呼び出される側ではその変数を使うことができても、呼び出し側の関数に返す術がありません。

だからと言って『Global変数』を増やすのもスマートな方法ではありませんし、メモリを多く消費してしまうことになります。

そこで登場するのが『ポインタ』になります。

例えば関数mainで値’x’を定義したとします。

その後関数mainから関数Aを呼び出す際に、値’x’のアドレス即ち『ポインタ』を渡します。

関数Bでは『ポインタ』の指すアドレスにある値を編集することによって、関数Aにも影響を及ぼすことができます。

図にすると次のような感じです。

void A(int *i)

{

  *i = 2;     ・・・  (iii)

  return;

}

int main(void)

{

  int x =1;  ・・・  (i)

  A(&x);     ・・・  (ii)

                 ・・・  (iv)

  return 0;

}

(i) スタック

未使用
x = 1 (Addr = 0xbfffff00)

main()関数内で’x = 1’が定義される。

(ii) スタック

未使用
復帰情報
i = 0xbfffff00
x = 1 (Addr = 0xbfffff00)

関数A内では変数 ’i’ に ’x’ のアドレスが渡される。

(iii) スタック

未使用
復帰情報
i = 0xbfffff00
x = 2 (Addr = 0xbfffff00)

関数A内でポインタ ’i’ のアドレス参照先の値を ”2” にする。

(iv) スタック

未使用
x = 2 (Addr = 0xbfffff00)

main()関数に戻ってくる時に関数Aのスタックは無くなる。

しかし、この時点で ‘x’ の値は関数Aによって変えられた状態になっている。

引数を『ポインタ』で渡すことの便利さを分かってもらえたでしょうか?

この関数の『ポインタ渡し』、これを『構造体』にすると更に便利な使い方ができるのですが、これについてはまた明日解説したいと思います。