モノ創りで国造りを

ハード/ソフト問わず知見をまとめてます

C言語のポインタ

自分は、プログラムから離れていると色々忘れてしまう程度のプログラマーなので
すぐ思い出せるようにメモ

ポインタの宣言

int *pointer;

この場合の*は宣言する変数がポインタであることを示すための目印。

ポインタに値を入れる

int hensu = 10;
int *pointer = &hensu;
//pointer = &hensu; と書いてもよい

変数hensuをポインタpointerに関連付けるには、
変数hensuのアドレスをポインタpointerに渡す。
変数hensuのアドレスは&hensuで取得できる。
宣言時以外でポインタにアドレスを渡す場合は、
*は不要でpointer = &hensuと記述する。

ポインタの値を取り出す

int hensu = 10;
int *pointer = &hensu;

*pointer = *pointer + 1;//ポインタの中身のhensuは11になる。

ポインタpointerが指し示すアドレスに格納されている値は、*pointerで取り出せる。
ポインタを宣言する際の*とは全く意味が異なるので、混乱を招く恐れあり。
なぜ同じマーク*をあてがってしまったのか・・・

関数宣言時の引数がポインタ

void kansu(int *hikisu){
    *hikisu = *hikisu + 1;
}

ただのポインタですら怖いのに、関数の引数がポインタだとどうなってしまうのか。
関数kansu使用時に引数ポインタhikisuのアドレス&hikisuをあてがえば良い。
1行目void kansu(int *hikisu){*hiksiuはポインタの宣言の*を示す。
2行目の*hikisu*hikisuの中身を取り出すための目印。何故同じマークにしたんだまったく。

void kansu(int *hikisu){
    *hikisu = *hikisu + 1;
}
void main(){
    int hensu = 10;
    kansu( &hensu ); //hensuが11になる
}

配列とポインタの関係

int array[3] = {1, 2, 3};

int *pointer1 = array;
int *pointer2 = &array[0];

配列array[3]のアドレスは2つの書き方array&array[0]で表現できる。
C言語の関数は返り値が1つしか取れないので不便だが、
ポインタと配列を組み合わせると色々できる(返り値なくても複数の値を操作できる)。

void kansu2(int *hikisu){
    hikisu[0]  = hikisu[0] + 1;
    hikisu[1] = hikisu[1] + 1;
    hikisu[2] = hikisu[2] + 1;
}

void mian(){
   int array[3] = {1, 2, 3};
   kansu2(array); //arrayの中身が{2,3,4}になる
}

関数名にポインタがついている場合

void *pointerKansu();

他人のコードでこんなの見たことある。まじ意味不明。。。
自分も昔(つい先日まで)は意味不明だった。
関数ポインタを使えば、関数のアドレスを活用できる。

void kansu1(){
    ....
}

void kansu2(){
    ....
}

void main(){
    void *pointerKansu();
    
    pointerKansu = kansu1;
    pointerKansu();//kansu1が実行される

    pointerKansu = kansu2;
    pointerkansu();//kansu2が実行される
}

関数を配列のように扱う

void nakamiKansu1(){
    ....
}

void nakamiKansu2(){
    ....
}

void main(){
    void (*pointerKansu[])() = {nakamiKansu1, nakamiKansu2};
    pointerKansu[0]();//nakamiKansu1が実行される
    pointerKansu[1]();//nakamiKansu2が実行される
}

関数ポインタを使えば、複数の関数をひとまとめにして、配列のように扱える。