DxLibFanに戻る C言語の初心者がよく躓く所pointer,ポインターポインタって実は私は躓かなかったんですけど、(良書のおかげ)結構躓くとの事ですので、ちと、簡単に説明します。名前のとおり、指す人(変数)です。 何を指すかというと、メモリのアドレスです。 アドレス等が何なのかは 入門書等に詳しくかかれているので、そこを見てください。 では、メモリのアドレスを指すにはどうすればいいのでしょうか? 以下のプログラムを見てください。 とまぁ、こんな感じです。 実は、この応用として、関数のポインタがあります。 関数のポインタポインタはアドレスを格納するための変数・・・だと言う事はすでに、入門書を見た方なら分かるはずです。実は、関数のアドレスを格納できる、ポインタもあるんです。え、でも、どんな型?とお思いでしょう。 実は、関数のポインタは定義されていないので、自分で定義する必要があります。 では、以下のような関数があるとしましょう。 int myprintf(const char *str){ return printf(ptr); }で、この関数のアドレスを記憶するためのポインタの宣言は、以下のようにします。 int (* funciton_address)(const char *);まぁ、こんな風に対応します。↓ しかし、 例えば、関数が以下のようになった場合、DxLibのDrawChipMapより、 int DrawChipMap( int MapWidth, int MapHeight, int *MapData, int ChipTypeNum, int *ChipGrHandle, int TransFlag, int MapDrawPointX, int MapDrawPointY, int MapDrawWidth, int MapDrawHeight, int ScreenX, int ScreenY ) ; いちいち関数のポインタの変数を宣言するのに、 int (*DrawChipMapNoKannsuuNoPointer)( int , int, int *, int , int *, int, int , int , int , int , int, int ) ; こうしなければならないのは非常に億劫です!! では、どうすれば・・・ で、ここになって出てくるのは、結構マイナ〜?なtypedefです。 typedefは自分の型を別の名前として登録する役目をするのは入門書に書いていたとおりです。 例えば、さっき出てきたmyprintfは以下のような感じに typedef int (*FP_MYPRINT_TYPE)(const char *); でも、なんか、変な宣言の仕方ですよね。私も最初は戸惑いました。 typedefって typedef int seisuu; 見たいに使うって入門書に書いていますよね。 しかし、関数のポインタをtypedefするには違うみたいですね。 こう覚えちゃうしかないと思います。 で、このtypedefしたものはどう使うんでしょうか? 以下のように使います。 FP_MYPRINT_TYPE function_pointer_name; /* 普通に変数のように宣言できる*/ function_pointer_name = myprintf;/* 関数の名前を=で入れると、アドレスを格納できる。*/ こうすれば関数ポインタの宣言が簡単になります。 そして、ここで一番大切なことは 関数のポインタは関数の名前を=で入れる事によって、アドレスを格納できる。 です。この意義については次のコールバック関数で説明します。
コールバック関数コールバック関数って結構、Windowを表示させるプログラムを組んでいる時はマニュアルとかに出てくる単語ですよね。私がプログラミングを始めて結構経っても、このコールバック関数の意味がわかりませんでした。 まぁ、関数のポインタを使う意義がここにあるのですけどね^^; さて、関数のポインタで触れたように関数のポインタは関数の名前を=で入れることによって、 アドレスを格納できました。 もしかしたら、このアドレスから、格納した関数を呼び出すことが出来るんではないか と考えた方がいましたら、正解です。 では、早速見てみましょう。 例えば、普通のintとかのポインタでは, int *p; int zittai = 0; p = &zittai; *p = 1;こうすることによって、zittaiの中には1を入れることが出来ましたね。では、関数のポインタでは、 int myprintf(const char *p){return printf(p);} int main(){ int (*my)(const char *); my = myprintf; my("myprintfが呼び出せた"); return 0; }こんな感じです。成るほど成るほど。(□。□-) フムフム では、ちと応用です。 #includeこんな感じのソースがありました。 以下のようにしたいとあなたは考えました。 for(i=0;i<6;i++){ ... を書くのがめんどくさいので、関数の中の関数(ここでは、printfやOutputDebugString)をとっかえひっかえしたい。 で、そうなるとすると、今までの知識で以下のように書けるはずです。 #includeエクセレント!!これで、関数の中の関数を6kai_printの第二引数でとっかえひっかえ出来るようになりました。 このとっかえひっかえできる関数(ここでは、myprintとmyoutputdebugstring)をコールバック関数といいます。(多分^^;) まぁ、関数のポインタの引数がついたものはその型に合った関数を入れればよいと、ソ〜(「・・)ン?名感じに覚えていれば良いかな?と思います。 C言語 小技JumpTable(ジャンプテーブル)ゲームプログラミングした事のある人ならわかるでしょう。if文が無くなり、速度向上の効果があるらしい、 しかし参照するときの変数がマイナスになったり、配列の宣言した数より添え字が大きくなるとエラー。 なので変数はunsigned系でcharがいいかも?でもcharって遅いし… BYTEかUINTか? ULONGLONGをジャンプテーブルの添え字にしちゃえ!Σ^)/d金魚のアホーアホー☆ミ 添え字にはintを奨励します。
TaskProcessingTypeJampTable?
重要報告:
実際、速度計測を行いました。その資料です。
|
SEO | [PR] 爆速!無料ブログ 無料ホームページ開設 無料ライブ放送 | ||