ポインタを理解するためのステップ
- 値と参照について
- 関数の引数について
- インスタンスについて
- ポインタがない場合とある場合のサンプルコード
- まとめ
値と参照について
メモリ上のデータは
- アドレス -> 1000 ~ 1003
- 値 -> メモリの中身
この2つで構成されているイメージです。
【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 関数で参照することはできました〜〜
アドレスが、適切に渡されていることもわかると思います。
まとめ
インスタンスの中身を更新したけりゃポインタを使え
補足
非常に非常に簡単にポインタのメリット、概念を説明するための記事です。他にもいっぱいメリットはあります。
- 戻り値が一つだが、複数の値をインスタンス内に保持し、予呼び元に返却することができる
- メモリの節約になる
などなど
詳細は他の記事を見てくれよな!