C言語で*(アスタリスク)や&(アンパサンド)って何だっけ?となったときのポインタ基礎です。
*a:ポインタの値渡し
&a:ポインタ渡し
*a
はaのアドレス(番地)の中の値を、&a
は番地そのものを渡します。
実際にサンプルコードで見てみます。
#include <stdio.h>
int main(void) {
int a = 100;
int *b;
printf("1: %d\n", a);
printf("2: %p\n", &a);
b = &a;
printf("3: %p\n", b);
*b = 255;
printf("4: %d\n", a);
}
結果
1: 100
2: 0x7ffcd185a1bc
3: 0x7ffcd185a1bc
4: 255
解説
1:aの中身は100
2:aの番地は0x7ffcd185a1bc
3:bの中身はaの番地(0x7ffcd185a1bc)
4:aの中身は255
コードについて見てみます。
int *b
は番地を格納するint型のポインタ変数bを宣言しています。bは番地を入れる変数として使います。
printf("2: %p\n", &a);
これでaの番地を表示しました。結果が0x7ffcd185a1bcであるのは実行したコンピュータのメモリ番地範囲が64bitだからです。番地範囲は実行環境に応じて以下のようになります。
bit | 範囲 |
---|---|
64 | 0xffffffffffffffff |
32 | 0xffffffff |
16 | 0xffff |
8 | 0xff |
値そのものも実行環境によって変化します。このときはたまたま0x7ffcd185a1bcでした。
b = &a
↑これはaの番地(0x7ffcd185a1bc)をbに代入しています。
*b = 255
↑これはbの中身が示す番地に255を代入しています。さて、aの番地は0x7ffcd185a1bcでした。この番地には255を代入したので、最後にaの中身を表示してみると結果が255になっていることが分かります。
bは番地を使ったaのショートカットとして使うことができそうです。その他にも大きな数値を渡したりする場合には値そのものを渡すのではなく、型と番地を渡してあげれば無駄なメモリを消費せずに高速に処理ができるところがポインタの役割でもあります。
左辺と右辺のときの考え方
*a:ポインタの値渡し
&a:ポインタ渡し
冒頭でこのように定義しました。この変数が左辺または右辺に置かれた場合は以下のようになります。
int *a, b, foo, *bar;
foo = *a;// aの(番地が示す)値を渡す
*a = foo;// aの(番地が示す)値としてfooを代入
bar = &b;// bの番地をbarに渡す;
&b = bar;// 番地自体は変数ではないのでコンパイルエラーが生じる。代入できるのは番地が示す中身。
注意点としては、参照を使った変数の処理では予めポインタ変数として宣言する必要があります。(例:int *a)
マイコンなどは決められたメモリアドレスに対して特有の機能が割り当てられているため、ポインタを使って番地の値を変更することで様々な機能を使い分けることができるようになっています。