ポインタ「Seven」の詳細な分析(関数ポインタに関する知識)

  個人ホームページ:みなさん、ようこそ->砂漠の下のコトカケヤナギ

 みんな、あなたはとても美しいです

 記事が役に立ったら

 ワンクリックでブロガーをサポートできます

 あなたの懸念のすべてのオンスは私が忍耐するための原動力です

 

 ☄: この問題の焦点:関数ポインタに関連するコンテンツ

  皆さんが幸せな勉強をして、毎日働いてくれることを願っています。 

コンテンツ

関数にアドレスがあるのはなぜですか?

関数アドレスとは何ですか?

関数ポインタ

では、関数ポインタを使用して関数を呼び出すにはどうすればよいですか 

関数呼び出しのメソッドの要約:

コールバック関数として使用される関数ポインタの呼び出し元インスタンス

複雑な関数ポインタ

次の通知:


関数にアドレスがあるのはなぜですか?

まず第一に、変数にはアドレスがあることを誰もが知っているので、関数にはアドレスがありますか?または、関数のアドレスは何ですか?下の図を見てください。

 まず、関数もコードの一部です。つまり、関数もCPUに読み込む必要があるため、CPUが読みやすいように、関数のアドレスが生成されます。

関数アドレスとは何ですか?

まず、関数のアドレスを表すには2つの方法があります。

1.直接関数名      2.アドレス関数名を取得します。

これらは両方とも関数のアドレスを表します。

 アセンブリを詳しく見てみましょう。

 

 ここでは、関数にアドレスがあり、そのアドレスはCPUによってアクセスされることがわかります。

関数ポインタ

前述のように、関数にはアドレスがありますが、関数のアドレスを保存するにはどうすればよいですか?何を受け取る?

もちろん、関数ポインタで受信されます。関数ポインタの形式は次のとおりです。

void Fan()
{
	printf("胡杨树下\n");
}

int main()
{
	Fan();
	void(*p)() = Fan;
	return 0;
}

タイプはデバッグによって確認できます。

ここのファンは&Fanも使用できます。

では、関数ポインタを使用して関数を呼び出すにはどうすればよいですか 

 図に示すように、これは関数呼び出しの概略図です。最初に関数ポインター変数を逆参照し、次にパラメーターを後ろに追加して、関数ポインターを使用して関数を呼び出す目的を完了します。

関数呼び出しのメソッドの要約:

void Test(int a)
{
	static i = 0;
	printf("第%d次调用,a = %d\n",++i,a);
}

int main()
{
	int a = 11223344;
	Test(a);

	void(*p)(int) = &Test;
	void(*q)(a) = Test;

	q(a);
	(*p)(a);

	return 0;
}

 初回は通常の呼び出しの場合で、aを印刷します。

2回目はq関数ポインターを介して呼び出され、&Testを挿入することで初期化されます。

3回目はp関数ポインターを介して呼び出され、初期化は初期化のためにテストに入れられます。

ここで、パラメーター名とタイプ名の両方を渡すことができることがわかります。

&address配列名の代わりに、関数名をアドレスとして直接使用することをお勧めします。また、関数ポインターの初期化で関数名を使用し、関数ポインターを関数として使用する場合はp()を使用してください。逆参照フォームは使用しないでください。

void Test(int a)
{
	static i = 0;
	printf("第%d次调用,a = %d\n",++i,a);
}

int main()
{
	int a = 11223344;
	Test(a);

	//void(*p)(int) = &Test;//不推荐
	void(*q)(a) = Test;

	q(a);
	//(*p)(a);//不推荐

	return 0;
}

コールバック関数として使用される関数ポインタの呼び出し元インスタンス

関数ポインタ、使用範囲は限られています。理解するためのコールバック関数として例を見てください。

void Scd()
{
	printf("输入有效\n");
}

void Fan(void(*p)())
{
	int a = 0;
	scanf("%d", &a);
	if (a != 0)
	{
		p();
	}
}

int main()
{
	Fan(Scd);
	return 0;
}

この関数のロジックは、Fan関数を呼び出し、パラメーターを関数ポインターとして渡し、数値を入力します。0でない場合は、Scd関数を呼び出して、「inputvalid」と出力します。

複雑な関数ポインタ

まず、古典的な例を見てみましょう。

(*(void(*)())0)();

まず、外部から分析する必要があります。最初にvoid(*)()は関数ポインター(関数ポインター)0はキャストであり、次に(*(関数ポインター)0)()これは再び関数ポインターです。

したがって、全体としては、0アドレスを関数ポインタに変換して呼び出す必要があります。

次に、説明されていない、より複雑な関数ポインター配列と関数ポインター配列へのポインターがありますが、理解方法は同じであり、関数ポインターとポインター配列の知識にも関連しています。

また、複雑なポインタや配列を解析する場合は、型である変数名を削除してから解析してください。

次の通知:

次号では、ダイナミックな開発に関する知識について説明します。

次号はもっとワクワクします〜!〜!〜!

おすすめ

転載: blog.csdn.net/m0_64770095/article/details/124281235