(この記事はCSDNフォーラムレポートからの抜粋です。学習のためのみです。違反がある場合は、連絡して削除してください)
通常の変数が定義されると、コンパイラは自動的に適切なメモリを割り当てます。関数についても同じことが言えます。コンパイルするとき、関数はコンパイルされてからメモリのブロックに配置されます。
(コンパイラはメモリを割り当てず、コンパイルされたコードもバイナリ形式でディスクに配置され、プログラムの実行開始時にのみメモリにロードされるため、上記のステートメントは実際には非常に不正確です)
関数の最初のアドレスをポインター変数に格納すると、このポインター変数を介して指定された関数を呼び出すことができます。関数の最初のアドレスを格納するこの特別なポインターは、関数ポインターと呼ばれます。
たとえば、関数 int func(int a);があります。
funcを指すことができる関数ポインタをどのように宣言しますか?
int(* func_p)(int);
実際、関数ポインタ変数の宣言形式は、funcが(* func_p)に置き換えられていることを除いて、関数funcの宣言と同じです。
なぜ括弧が必要なのですか?かっこが必要ない場合、 int * func_p(int); はポインタを返す関数を宣言するためです。かっこは、このあいまいさを回避するためのものです。
さらにいくつかの関数ポインタ宣言を見てみましょう。
int (*f1)(int); // 传入int,返回int
void (*f2)(char*); //传入char指针,没有返回值
double* (*f3)(int, int); //传递两个整数,返回 double指针
関数ポインタの特定の使用法を見てみましょう。
# include <stdio.h>
typedef void (*work)() Work; // typedef 定义一种函数指针类型
void xiaobei_work() {
printf("小北工作就是写代码");
}
void shuaibei_work() {
printf("帅北工作就是摸鱼")
}
void do_work(Work worker) {
worker();
}
int main(void)
{
Work x_work = xiaobei_work;
Work s_work = shuaibei_work;
do_work(x_work);
do_work(s_work);
return 0;
}
出力:
小北工作就是写代码
帅北工作就是摸鱼
実際、ここでは関数ポインターを使用する目的で少し使用されていますが、関数ポインターの最大の利点は関数を変数にすることであることを誰もが理解する必要があります。
関数をパラメーターとして他の関数に渡すことができるので、ポリモーフィズムのプロトタイプがあります。さまざまな関数を渡して、さまざまな動作を実現できます。
void qsort(void* base, size_t num, size_t width, int(*compare)(const void*,const void*))
これは、C標準ライブラリでのqsort関数の宣言です 。最後のパラメータでは、関数ポインタを渡す必要があります。この関数ポインタは、2つの要素を比較する役割を果たします。
2つの要素を比較する方法は呼び出し元にしか知られていないため、2つの要素のサイズを決定する方法を関数ポインターの形式でqsortに指示する必要があります。
さて、ここでは関数ポインタを簡単に紹介します。