関数ポインタ変数の配列をつかって複数の自作関数を実行することのメリットは自作関数が実行される順序を入れ替えることができることにあります

ソーラー「さて


こう思った人もいるんじゃないかな?


void newmadefunction(void) {


printf("青い海です\n");


return ;

}


と定義された自作関数newmadefunctionがあるとします


このとき


関数ポインタ変数宣言


void(*ptf)(void);


により作製された


関数ポインタ変数ptfに自作関数newmadefunctionの


アドレスを


ptf=newmadefunction;



代入したのち


*ptf


を用いて


自作関数newmadefunctionを実行してみなくても


普通に


自作関数newmadefunctionを


newmadefunction();



実行すればいいのでは?


関数ポインタ変数を用いて


自作関数newmadefunctionを


*ptf



実行する必要はないのでは



思われる方がおられるかもしれません」


アレサ「そういえば そうですの」


ソーラー「そこで


関数ポインタ変数を用いて


自作関数を


実行することの利点を述べてみたいと思います。」


アレサ「どのような例がでるのかしら・・・」


ソーラー「まず 次のプログラムを


ご覧ください


#include <stdio.h>


void newmadefunction1(void) {


printf("青い海です\n");


return;

}


void newmadefunction2(void) {


printf("金色の海です\n");


return;

}


void newmadefunction3(void) {


printf("水色の海です\n");


return;

}


int main(void) {


void(*ptf[3])(void);


ptf [0]= newmadefunction1;

ptf [1]= newmadefunction2;

ptf [2]= newmadefunction3;


(*ptf[0])();

(*ptf[1])();

(*ptf[2])();


return 0;


}


コンパイル結果(EAZY IDECの場合)


青い海です

金色の海です

水色の海です


Visual studioの場合


青い海です

金色の海です

水色の海です



ソーラー「このプログラムでは


関数ポインタ変数の配列宣言


void(*ptf[3])(void);


により


関数ポインタ変数が


ptf[0]

ptf[1]

ptf[2]


と3つ生成されるんだよ


まとめて


関数ポインタ変数を作製したいときには


この方法は便利だよね。


関数ポインタ変数名を


ptf1

ptf2

ptf3

のように

3つ考えて

関数ポインタ変数宣言を3つ


void(*ptf1)(void);

void(*ptf2)(void);

void(*ptf3)(void);


と記述しなくてもいいからね。


後は


定義されている自作関数名


newmadefunction1

newmadefunction2

newmadefunction3


作製された


関数ポインタ変数

ptf[0]

ptf[1]

ptf[2]

ptf[0]= newmadefunction1;

ptf[1]= newmadefunction2;

ptf[2]= newmadefunction3;


と代入すれば


*ptf[0]

*ptf[1]

*ptf[2]


プログラムの実行時


機械語に翻訳された自作関数が格納されているメモリにアクセスして


自作関数

newmadefunction1

newmadefunction2

newmadefunction3


の働きをすることになります。


ですので


(*ptf[0])();

(*ptf[1])();

(*ptf[2])();


と記述して


コンパイル結果に


青い海です

金色の海です

水色の海です


が表示できるってわけだね。


つまり


自作関数

newmadefunction1

newmadefunction2

newmadefunction3


を実行できるってわけだね。


ここで


このプログラムの


(*ptf[0])();

(*ptf[1])();

(*ptf[2])();


の部分を


int i;


for(i=0;i<3;i++){


(*ptf[i])();


}


と書き換えて実行することができます。


その時のプログラムはこちらです

👇

#include <stdio.h>


void newmadefunction1(void) {


printf("青い海です\n");


return;

}


void newmadefunction2(void) {


printf("金色の海です\n");


return;

}


void newmadefunction3(void) {


printf("水色の海です\n");


return;

}


int main(void) {


void(*ptf[3])(void);


ptf [0]= newmadefunction1;

ptf [1]= newmadefunction2;

ptf [2]= newmadefunction3;


int i;


for(i=0;i<3;i++){


(*ptf[i])();


}



return 0;


}


コンパイル結果(EAZY IDECの場合)


青い海です

金色の海です

水色の海です


Visual studioの場合


青い海です

金色の海です

水色の海です


ソーラー「どう?アレサ


            🌞配列🌞


を用いて


簡単にプログラムを記述することができたね」



今のこのプログラムは


printf("青い海です\n");

printf("金色の海です\n");

printf("水色の海です\n");



関数のポインタ変数と配列のシステムを使って


実行しているというわけなんだよ」


アレサ「そうなのですね。


関数のポインタ変数と配列のシステムを使っているといっても


printf("青い海です\n");

printf("金色の海です\n");

printf("水色の海です\n");


が実行されているだけなのですね。」


ソーラー「ところで


あるプログラムで


printf("青い海です\n");

printf("金色の海です\n");

printf("水色の海です\n");


が記述されているとします


この命令文の実行順序を


printf("水色の海です\n");

printf("金色の海です\n");

printf("青い海です\n");


に入れ替えて実行してみたいと思います


ふつうは


printf("青い海です\n");

printf("金色の海です\n");

printf("水色の海です\n");


printf("水色の海です\n");

printf("金色の海です\n");

printf("青い海です\n");


と記述しなおせばいいということになりますね。」


アレサ「ソーラーさん そうですね 簡単ですね。」


ソーラー「では


関数のポインタ変数と配列のシステムが用いられた


このプログラムの


👇

#include <stdio.h>


void newmadefunction1(void) {


printf("青い海です\n");


return;

}


void newmadefunction2(void) {


printf("金色の海です\n");


return;

}


void newmadefunction3(void) {


printf("水色の海です\n");


return;

}


int main(void) {


void(*ptf[3])(void);


ptf [0]= newmadefunction1;

ptf [1]= newmadefunction2;

ptf [2]= newmadefunction3;


int i;


for(i=0;i<3;i++){


(*ptf[i])();


}



return 0;


}


コンパイル結果(EAZY IDECの場合)


青い海です

金色の海です

水色の海です


Visual studioの場合


青い海です

金色の海です

水色の海です



👆

ビルド実行結果を


青い海です

金色の海です

水色の海です


から


水色の海です

金色の海です

青い海です


に変えて


コマンドプロンプト画面に表示したい場合は


どうしたらいいとおもうかな?」


アレサ「ふ~んん


int i;


for(i=0;i<3;i++){


(*ptf[i])();


}


の部分は


(*ptf[0])();

(*ptf[1])();

(*ptf[2])();


と等しいものです


(*ptf[0])();

(*ptf[1])();

(*ptf[2])();


が実行されると


printf("青い海です\n");

printf("金色の海です\n");

printf("水色の海です\n");


が実行されて


青い海です

金色の海です

水色の海です



コマンドプロンプト画面に表示されます


なら


(*ptf[2])();

(*ptf[1])();

(*ptf[0])();


が実行されれば


printf("水色の海です\n");

printf("金色の海です\n");

printf("青い海です\n");


が実行されて


水色の海です

金色の海です

青い海です



コマンドプロンプト画面に表示されることになります。


ということは


プログラムの


int i;


for(i=0;i<3;i++){


(*ptf[i])();


}


の部分を


int i;


for(i=0;i<3;i++){


(*ptf[2-i])();


}


のように記述しなおしたらよいのではないですか?」


ソーラー「そうなんだ


やったね アレサ💖


その時のプログラムは


こちらだね

👇

      

#include <stdio.h>


void newmadefunction1(void) {


printf("青い海です\n");


return;

}


void newmadefunction2(void) {


printf("金色の海です\n");


return;

}


void newmadefunction3(void) {


printf("水色の海です\n");


return;

}


int main(void) {


void(*ptf[3])(void);


ptf [0]= newmadefunction1;

ptf [1]= newmadefunction2;

ptf [2]= newmadefunction3;


int i;


for(i=0;i<3;i++){


(*ptf[2-i])();


}



return 0;


}


コンパイル結果(EAZY IDECの場合)


水色の海です

金色の海です

青い海です


Visual studioの場合


水色の海です

金色の海です

青い海です


ソーラー「このプログラムでは


青い海です

金色の海です

水色の海です


の順序を入れ替えた


水色の海です

金色の海です

青い海です


がコマンドプロンプト画面に表示されています


ようは


printf("青い海です\n");

printf("金色の海です\n");

printf("水色の海です\n");


の実行順序を


     関数のポインタ変数と配列のシステムを用いて

        


printf("水色の海です\n");

printf("金色の海です\n");

printf("青い海です\n");


に入れ替えたというわけなんです。



         このことはとても重要なことなんだよ。


例えば


青い海です

金色の海です

水色の海です

水色の海です

青い海です

水色の海です

青い海です

青い海です

金色の海です

水色の海です

金色の海です

水色の海です

青い海です

金色の海です

金色の海です


とコマンドプロンプト画面に


表示されている状態から


順序を逆に


金色の海です

金色の海です

青い海です

水色の海です

金色の海です

水色の海です

金色の海です

青い海です

青い海です

水色の海です

青い海です

水色の海です

水色の海です

金色の海です

青い海です



とコマンドプロンプト画面に


表示されている状態に変更したい場合に



printf("青い海です\n");

printf("金色の海です\n");

printf("水色の海です\n");

printf("水色の海です\n");

printf("青い海です\n");

printf("水色の海です\n");

printf("青い海です\n");

printf("青い海です\n");

printf("金色の海です\n");

printf("水色の海です\n");

printf("金色の海です\n");

printf("水色の海です\n");

printf("青い海です\n");

printf("金色の海です\n");

printf("金色の海です\n");


と記述されている状態を


実行順序を逆に入れ替えて


printf("金色の海です\n");

printf("金色の海です\n");

printf("青い海です\n");

printf("水色の海です\n");

printf("金色の海です\n");

printf("水色の海です\n");

printf("金色の海です\n");

printf("青い海です\n");

printf("青い海です\n");

printf("水色の海です\n");

printf("青い海です\n");

printf("水色の海です\n");

printf("水色の海です\n");

printf("金色の海です\n");

printf("青い海です\n");


と記述する方法もあるのですが


とても大変です


そこで最初に


printf("青い海です\n");

printf("金色の海です\n");

printf("水色の海です\n");

printf("水色の海です\n");

printf("青い海です\n");

printf("水色の海です\n");

printf("青い海です\n");

printf("青い海です\n");

printf("金色の海です\n");

printf("水色の海です\n");

printf("金色の海です\n");

printf("水色の海です\n");

printf("青い海です\n");

printf("金色の海です\n");

printf("金色の海です\n");


と記述されている状態から


簡単に


実行順序を入れ替えて


printf("金色の海です\n");

printf("金色の海です\n");

printf("青い海です\n");

printf("水色の海です\n");

printf("金色の海です\n");

printf("水色の海です\n");

printf("金色の海です\n");

printf("青い海です\n");

printf("青い海です\n");

printf("水色の海です\n");

printf("青い海です\n");

printf("水色の海です\n");

printf("水色の海です\n");

printf("金色の海です\n");

printf("青い海です\n");


に変更して


実行することができるために


最初から


printf("青い海です\n");

printf("金色の海です\n");

printf("水色の海です\n");

printf("水色の海です\n");

printf("青い海です\n");

printf("水色の海です\n");

printf("青い海です\n");

printf("青い海です\n");

printf("金色の海です\n");

printf("水色の海です\n");

printf("金色の海です\n");

printf("水色の海です\n");

printf("青い海です\n");

printf("金色の海です\n");

printf("金色の海です\n");



関数のポインタ変数と配列のシステムを用いて


記述しておきます。


printf("青い海です\n");

printf("金色の海です\n");

printf("水色の海です\n");

printf("水色の海です\n");

printf("青い海です\n");

printf("水色の海です\n");

printf("青い海です\n");

printf("青い海です\n");

printf("金色の海です\n");

printf("水色の海です\n");

printf("金色の海です\n");

printf("水色の海です\n");

printf("青い海です\n");

printf("金色の海です\n");

printf("金色の海です\n");


を実行するために


printf("青い海です\n");

printf("金色の海です\n");

printf("水色の海です\n");


を自作関数


void newmadefunction1(void) {


printf("青い海です\n");


return;

}


void newmadefunction2(void) {


printf("金色の海です\n");


return;

}


void newmadefunction3(void) {


printf("水色の海です\n");


return;

}


に設定して


関数のポインタ変数の配列宣言


void(*ptf[15])(void);


により生成される


関数のポインタ変数の配列


ptf[0]

ptf[1]

ptf[2]

ptf[3]

ptf[4]

ptf[5]

ptf[6]

ptf[7]

ptf[8]

ptf[9]

ptf[10]

ptf[11]

ptf[12]

ptf[13]

ptf[14]


自作関数

newmadefunction1

newmadefunction2

newmadefunction3


のアドレスを


ptf[0]=newmadefunction1;

ptf[1]=newmadefunction2;

ptf[2]=newmadefunction3;

ptf[3]=newmadefunction3;

ptf[4]=newmadefunction1;

ptf[5]=newmadefunction3;

ptf[6]=newmadefunction1;

ptf[7]=newmadefunction1;

ptf[8]=newmadefunction2;

ptf[9]=newmadefunction3;

ptf[10]=newmadefunction2;

ptf[11]=newmadefunction3;

ptf[12]=newmadefunction1;

ptf[13]=newmadefunction2;

ptf[14]=newmadefunction2;


のように代入し


int i;

for(i=0;i<15;i++){

(*ptf[i])();

}


と記述しておけば


int i;

for(i=0;i<15i++){

(*ptf[14-i])();

}


と記述するだけで


printf("金色の海です\n");

printf("金色の海です\n");

printf("青い海です\n");

printf("水色の海です\n");

printf("金色の海です\n");

printf("水色の海です\n");

printf("金色の海です\n");

printf("青い海です\n");

printf("青い海です\n");

printf("水色の海です\n");

printf("青い海です\n");

printf("水色の海です\n");

printf("水色の海です\n");

printf("金色の海です\n");

printf("青い海です\n");


が実行できるんです


つまり


以下のプログラムの

👇

#include <stdio.h>


void newmadefunction1(void) {


printf("青い海です\n");


return;

}


void newmadefunction2(void) {


printf("金色の海です\n");


return;

}


void newmadefunction3(void) {


printf("水色の海です\n");


return;

}


int main(void) {


void(*ptf[15])(void);


ptf[0]=newmadefunction1;

ptf[1]=newmadefunction2;

ptf[2]=newmadefunction3;

ptf[3]=newmadefunction3;

ptf[4]=newmadefunction1;

ptf[5]=newmadefunction3;

ptf[6]=newmadefunction1;

ptf[7]=newmadefunction1;

ptf[8]=newmadefunction2;

ptf[9]=newmadefunction3;

ptf[10]=newmadefunction2;

ptf[11]=newmadefunction3;

ptf[12]=newmadefunction1;

ptf[13]=newmadefunction2;

ptf[14]=newmadefunction2;


int i;

for(i=0;i<15;i++){

(*ptf[i])();

}

return 0;


}



ビルド実行結果


青い海です

金色の海です

水色の海です

水色の海です

青い海です

水色の海です

青い海です

青い海です

金色の海です

水色の海です

金色の海です

水色の海です

青い海です

金色の海です

金色の海です


👆



       (*ptf[i])();の部分を(*ptf[14-i])();


と記述し直すだけでよいというわけです。


その時のプログラムはこちらです

👇

#include <stdio.h>


void newmadefunction1(void) {


printf("青い海です\n");


return;

}


void newmadefunction2(void) {


printf("金色の海です\n");


return;

}


void newmadefunction3(void) {


printf("水色の海です\n");


return;

}


int main(void) {


void(*ptf[15])(void);


ptf[0]=newmadefunction1;

ptf[1]=newmadefunction2;

ptf[2]=newmadefunction3;

ptf[3]=newmadefunction3;

ptf[4]=newmadefunction1;

ptf[5]=newmadefunction3;

ptf[6]=newmadefunction1;

ptf[7]=newmadefunction1;

ptf[8]=newmadefunction2;

ptf[9]=newmadefunction3;

ptf[10]=newmadefunction2;

ptf[11]=newmadefunction3;

ptf[12]=newmadefunction1;

ptf[13]=newmadefunction2;

ptf[14]=newmadefunction2;


int i;

for(i=0;i<15;i++){

(*ptf[14-i])();

}

return 0;


}


ビルド実行結果


金色の海です

金色の海です

青い海です

水色の海です

金色の海です

水色の海です

金色の海です

青い海です

青い海です

水色の海です

青い海です

水色の海です

水色の海です

金色の海です

青い海です


アレサ「自作関数の実行順序が簡単に入れ替わっています」


ソーラー「そう このように


関数の実行順序を


簡単に入れ替えて実行するために


関数のポインタ変数と配列のシステムは用いられるんだよ


printf("青い海です\n");

printf("金色の海です\n");

printf("水色の海です\n");



自作関数


newmadefunction1

newmadefunction2

newmadefunction3


の定義にもちいて


自作関数


newmadefunction1

newmadefunction2

newmadefunction3


を生成したり


関数のポインタ変数の配列宣言


void(*ptf[15])(void);


により生成される


関数のポインタ変数の配列


ptf[0]

ptf[1]

ptf[2]

ptf[3]

ptf[4]

ptf[5]

ptf[6]

ptf[7]

ptf[8]

ptf[9]

ptf[10]

ptf[11]

ptf[12]

ptf[13]

ptf[14]


自作関数

newmadefunction1

newmadefunction2

newmadefunction3


のアドレスを


ptf[0]=newmadefunction1;

ptf[1]=newmadefunction2;

ptf[2]=newmadefunction3;

ptf[3]=newmadefunction3;

ptf[4]=newmadefunction1;

ptf[5]=newmadefunction3;

ptf[6]=newmadefunction1;

ptf[7]=newmadefunction1;

ptf[8]=newmadefunction2;

ptf[9]=newmadefunction3;

ptf[10]=newmadefunction2;

ptf[11]=newmadefunction3;

ptf[12]=newmadefunction1;

ptf[13]=newmadefunction2;

ptf[14]=newmadefunction2;


のように代入したりするところに


手間がかかると思います



一度


ptf[0]=newmadefunction1;

ptf[1]=newmadefunction2;

ptf[2]=newmadefunction3;

ptf[3]=newmadefunction3;

ptf[4]=newmadefunction1;

ptf[5]=newmadefunction3;

ptf[6]=newmadefunction1;

ptf[7]=newmadefunction1;

ptf[8]=newmadefunction2;

ptf[9]=newmadefunction3;

ptf[10]=newmadefunction2;

ptf[11]=newmadefunction3;

ptf[12]=newmadefunction1;

ptf[13]=newmadefunction2;

ptf[14]=newmadefunction2;


まで実行しておけば


printf("青い海です\n");

printf("金色の海です\n");

printf("水色の海です\n");


の実行順序を


関数のポインタ変数と配列のシステムを


用いて


簡単に管理できることになるというわけです。」

  • Twitterで共有
  • Facebookで共有
  • はてなブックマークでブックマーク

作者を応援しよう!

ハートをクリックで、簡単に応援の気持ちを伝えられます。(ログインが必要です)

応援したユーザー

応援すると応援コメントも書けます

新規登録で充実の読書を

マイページ
読書の状況から作品を自動で分類して簡単に管理できる
小説の未読話数がひと目でわかり前回の続きから読める
フォローしたユーザーの活動を追える
通知
小説の更新や作者の新作の情報を受け取れる
閲覧履歴
以前読んだ小説が一覧で見つけやすい
新規ユーザー登録無料

アカウントをお持ちの方はログイン

カクヨムで可能な読書体験をくわしく知る