0
@maejimayuto

C言語ポインタを理解するための簡単な例〜誰でもわかるポインタのメリット〜

ポインタを理解するためのステップ

  • 値と参照について
  • 関数の引数について
  • インスタンスについて
  • ポインタがない場合とある場合のサンプルコード
  • まとめ

値と参照について

メモリ上のデータは

  • アドレス -> 1000 ~ 1003
  • 値 -> メモリの中身

この2つで構成されているイメージです。
image.png
【C言語】ポインタ

アドレスのことを参照
値のことを値
と呼ぶのが一般的です。

関数の引数について

C 言語では、関数の引数に しか渡すことができません。
なので、関数の引数にインスタンスを渡し、そのインスタンスに関数内で変更を加えるためには ポインタというアドレスを値として扱う変数 が必要になります!!!(ここ重要)

ポインタがない場合とある場合のサンプルコード

Main.c
#include <stdio.h>
typedef struct list {
    int first;
    int second;
    int sum;
    int sub;
} list;

// ポインタなしの関数
void sum_and_sub(list list) {
    printf("list address in sum(): %d\n", &list);
    list.sum = list.first + list.second;
    printf("sum in sum(): %d\n", list.sum);
    list.sub = list.first - list.second;
    printf("sub in sum(): %d\n", list.sub);
}

// ポインタありの関数
void sum_and_sub_pointer(list *list) {
    printf("list address in sum_pointer(): %d\n", list);
    list->sum = list->first + list->second;
    printf("sum in sum_pointer(): %d\n", list->sum);
    list->sub = list->first - list->second;
    printf("sub in sum_pointer(): %d\n", list->sub);
}

int main(void) {
    struct list list1;
    list1.first = 1;
    list1.second = 5;
    list1.sum = 0;
    list1.sub = 0;
    printf("list1 address in main(): %d\n", &list1);
    sum_and_sub(list1);
    printf("sum by sum(): %d\n", list1.sum);
    printf("sub by sum(): %d\n", list1.sub);
    sum_and_sub_pointer(&list1);
    printf("sum by sum_pointer: %d\n", list1.sum);
    printf("sub by sum_pointer: %d\n", list1.sub);
}
list1 address in main(): -1886710432
list address in sum(): -1886710416
sum in sum(): 6
sub in sum(): -4
sum by sum(): 0
sub by sum(): 0
list address in sum_pointer(): -1886710432
sum in sum_pointer(): 6
sub in sum_pointer(): -4
sum by sum_pointer: 6
sub by sum_pointer: -4

sum 関数では、呼び元で定義している .first, .second を受け取ることはできています。
が、 sum 関数内で .total に代入した値を呼び元の main 関数で参照することはできませんでした。

sum_pointer 関数では、 sum_pointer 関数内で .total に代入した値を呼び元の main 関数で参照することはできました〜〜

アドレスが、適切に渡されていることもわかると思います。

まとめ

インスタンスの中身を更新したけりゃポインタを使え

補足

非常に非常に簡単にポインタのメリット、概念を説明するための記事です。他にもいっぱいメリットはあります。
- 戻り値が一つだが、複数の値をインスタンス内に保持し、予呼び元に返却することができる
- メモリの節約になる

などなど
詳細は他の記事を見てくれよな!

0
ユーザー登録して、Qiitaをもっと便利に使ってみませんか。
  1. あなたにマッチした記事をお届けします
    ユーザーやタグをフォローすることで、あなたが興味を持つ技術分野の情報をまとめてキャッチアップできます
  2. 便利な情報をあとで効率的に読み返せます
    気に入った記事を「ストック」することで、あとからすぐに検索できます
prum
エンジニアが日本で一番成長できる環境を作り続ける
この記事は以下の記事からリンクされています

コメント

(編集済み)

C++ なら、参照渡し(変数共有)でアドレスを意識しなくて済むので楽なんですけどね。
あと、アドレスの表示は %p を使いましょう。

C++
#include <stdio.h>
typedef struct list {
    int first;
    int second;
    int sum;
    int sub;
} list;

// 参照渡し(変数共有)の関数
void sum_and_sub(list &list) {
    printf("list address in sum(): %p\n", &list);
    list.sum = list.first + list.second;
    printf("sum in sum(): %d\n", list.sum);
    list.sub = list.first - list.second;
    printf("sub in sum(): %d\n", list.sub);
}

int main(void) {
    struct list list1 = {
        .first = 1,
        .second = 5,
        .sum = 0,
        .sub = 0,
    };
    printf("list1 address in main(): %p\n", &list1);
    sum_and_sub(list1);
    printf("sum by sum(): %d\n", list1.sum);
    printf("sub by sum(): %d\n", list1.sub);
}
実行結果
list1 address in main(): 0xffffcc30
list address in sum(): 0xffffcc30
sum in sum(): 6
sub in sum(): -4
sum by sum(): 6
sub by sum(): -4
1

@fujitanozomu ありがとうございます!

予備元→呼び元 修正 by fujitanozomu 2021/04/23 01:27

0

アドレス表示用の変数があるんですね!
ありがとうございます。
勉強になります!

0

ポインタのメリットということですが、参照が使えない(≒欠陥)のを補う程度のものであるならば「メリット」とは言いづらいのでは?

1

リンク先は、maejimayutoさんのサイトですか?

0

そうではないです

0
(編集済み)

そうではないです

サイトの作者に許可を取ったか、偶然画像のピクセル値の全てが一致したということですね、理解しました。失礼いたしました。

0
あなたもコメントしてみませんか :)
ユーザー登録
すでにアカウントを持っている方はログイン
記事投稿イベント開催中
新人プログラマ応援 - みんなで新人を育てよう!
~
Java開発者のためのAzure入門
~