アドレスは、16進数で表された数で表されます。

<STEP1>
アドレスをのぞいてみよう!
scanfをするとき、変数だと「&変数名」がアドレス、配列だと「配列名」がアドレスだと学習しましたね。
アドレスを調べるときは、16進数の数値を、「%p」を使ってみることができます。

#include <stdio.h>
int main(){
    int a; //変数を宣言
    int b[2]; //配列を宣言
    printf("%p\n", &a); //変数のアドレスを調べる
    printf("%p\n", b); //アドレスの変数を調べる
    return 0;
}

アドレスは、変数や配列を宣言した瞬間に勝手に割り当てがされます。PCや環境によって、アドレスが違います。


<STEP2>
変数や配列に値を代入しても、アドレスは変わらないことを確認しましょう
#include <stdio.h>
int main(){
    int a;
    int b[2];
    printf("%p\n", &a);
    printf("%p\n", b);
    
    a = 1;
    b[0] = 3;
    printf("%p\n", &a);
    printf("%p\n", b);
    return 0;
}
先ほどのコードに続いて、値を代入したのちにアドレスの確認作業をしてみました。
値を代入しても、アドレスが変化しないことに注意してください。
「C言語では、変数や配列の宣言時に、メモリが確保される」と学習してきましたが、メモリと一緒に、アドレスも確定します。


<STEP3>
アドレスを格納する特殊な変数「ポインタ変数」
int *ポインタ名;  //int型の変数のアドレスを格納する変数の宣言です
char *ポインタ名;  //char型の変数のアドレスを格納する変数の宣言です
double *ポインタ名;  //double型の変数のアドレスを格納する変数の宣言です

#include <stdio.h>
int main(){
    int a;
    printf("%p\n", &a);

    int *pa;  //ポインタの変数宣言をする際には*が必要です。
    pa = &a;  //これで、aのアドレスが、ポインタに格納されました。
    printf("%p\n", pa);
    return 0;
}


<STEP4>
ポインタは、変数の住所のこと!
をきちんと理解してください。

変数の住所がわかったら、変数名を指定しないでも、変数の値を取り出せそうじゃないですか??
変数の値を取り出したいときは、ポインタ名に、*をつけて、「*ポインタ名」で取り出すことができます。

#include <stdio.h>
int main(){
    int a = 2;
    int *pa;
    pa = &a; //変数aのアドレスを、paにコピー
    printf("%d\n", a);
    printf("%d\n", *pa);  //*ポインタ名で、変数aの中身にアクセスできる!
    return 0;
}


<STEP3,4補足>
ポインタは、初期化も可能です。
STEP3の例ですと、
「 int *pa = &a; 」
で、初期化ができます。


<step5>
STEP4でも扱いましたが、*paは、変数aの中身のことでした。
変数aの中身に、直接値を代入したら、変数aはどうなるでしょうか。

#include <stdio.h>
int main(){
    int a = 2;
    int *pa = &a;
    printf("%d\n", a);

    *pa = 56;
    printf("%d\n", a);
    return 0;
}

*paは、変数の中身に直接アクセスできるので、*paに値を代入するということは、つまり、変数aに値を代入するという意味でした。