【Cとポインタ】関数ポインタ

6812 ワード

一、関数ポインタ
1)定義:関数を指すポインタ変数.「関数ポインタ」自体は、関数を指すポインタ変数です.
2)区別:これはポインタ変数で整数変数、文字型、配列を指すことができるように、ここでは関数を指す.
3)説明:Cコンパイル時、各関数には、関数ポインタが指すアドレスであるエントリアドレスがある.関数を指すポインタ変数があれば、ポインタ変数で他のタイプの変数を参照できるように、このポインタ変数で関数を呼び出すことができます.これらの概念は一致しています.
4)用途:関数ポインタには、呼び出し関数と関数のパラメータの2つの用途があります.
5)関数ポインタの宣言方法は、関数タイプ(フラグポインタ変数名)(パラメータリスト)注1:関数タイプは関数の戻りタイプを示します.
「(フラグポインタ変数名)」の括弧は省略できませんが、全体を省略すると1つの関数説明となり、返されるデータ型がポインタの関数であることを説明します
[パラメータリスト](Parameter List)は、ポインタ変数が指す関数のパラメータリストを表します.例:int func(int x);/*関数*/int(*f)(int x);/*を宣言します.関数ポインタを宣言*/f=func;/*func関数のヘッダアドレスをポインタf*/付与時に関数funcは括弧もパラメータも持たず、funcは関数のヘッダアドレスを表すため、付与後、ポインタfは関数func(x)のコードのヘッダアドレスを指す.注2:関数カッコ内のパラメータは、状況に応じて異なります.次のプログラムでは、関数ポインタが関数を呼び出す方法を説明します.例1、
    
#include<stdio.h>
int max(int x,int y)//   
{ 
	return(x>y?x:y); 
}
int main()
{
	int (*ptr)(int, int);//               (   ++  --) 
	int a,b,c;
	ptr=max;//         
	scanf("%d%d",&a,&b);
	c=(*ptr)(a,b);//     
	printf("a=%d,b=%d,max=%d",a,b,c);
}

 
例2ですが、一部のコンパイラでは通過できません.この例の補足は以下の通りです.1.関数ポインタタイプの定義:typedef int(*fun_ptr)(int,int);  2.変数、付与:fun_ptr max_func=max; すなわち,関数ポインタに付与される関数は,関数ポインタが指す関数プロトタイプと一致するはずである.       
#include<stdio.h> 
void FileFunc() 
{ 
	printf("FileFunc
"); } void EditFunc() { printf("EditFunc
"); } int main() { typedef void (*funcp)();// funcp pfun= FileFunc; // pfun(); // pfun = EditFunc;// pfun(); }

  
6)ポインタ関数と関数ポインタの区別ポインタ関数とは,戻り値がポインタの関数,すなわち本質が関数であることを意味する.関数には戻りタイプ(値を返さない場合は値なし)があることは知っていますが、ポインタ関数の戻りタイプはあるタイプのポインタです.
戻りタイプ識別子*戻り名前(形式パラメータテーブル){
かんすうたい
}戻りタイプは、任意の基本タイプおよび複合タイプであってもよい.ポインタを返す関数の用途は非常に広い.実際、各関数には、あるタイプのポインタを返さなくても、ポインタに相当するエントリアドレスがあります.たとえば、関数が整数値を返すのは、実際にはポインタ変数の値を返すことに相当しますが、この場合の変数は関数自体であり、関数全体が「変数」に相当します.たとえば、次のポインタ関数の例を返します.
//               ,                                                               
#include<iostream>                                                                                       
using namespace std;                                                                                     
float *find(float (*p)[4],int m)//     m                                                 
{                                                                                                        
	float *pf=NULL;                                                                                         
	pf=*(p+m);//p          , *                                                          
	return pf;                                                                                              
}                                                                                                        
                                                                                                         
int main()                                                                                               
{                                                                                                        
	float score[][4]={{50,51,52,55},{70,70,40,80},{77,99,88,67}};//      ,                   
	float *pf=NULL;//                                                                          
	int i,m;                                                                                                
	cout<<"             :";                                                                    
	cin>>m;                                                                                                 
	pf=find(score,m);//         ,                                                         
	for(i=0;i<4;i++)                                                                                        
		cout<<*(pf+i)<<" ";                                                                                    
	cout<<endl;                                                                                             
	return 0;                                                                                               
}                                                                                                        

 
学生学号は0番から計算され、関数find()はポインタ関数として定義され、起形パラメータはポインタが4つの要素を含む1次元配列を指すポインタ変数である.pointer+1はscoreの最初の行を指します.*(pointer+1)は、最初の行の0番目の要素を指します.ptは浮動小数点型変数を指すポインタ変数である.main()関数でfind()関数を呼び出し、score配列のヘッダアドレスをpointerに渡す.  
関数ポインタは関数を指すポインタ変数であるため、「関数ポインタ」自体はまずポインタ変数であるべきであるが、このポインタ変数は関数を指すにすぎない.これは、ポインタ変数で整数変数、文字型、配列を指すことができるように、ここでは関数を指す.前述したように、Cはコンパイル時に、各関数にエントリアドレスがあり、このエントリアドレスは関数ポインタが指すアドレスである.関数を指すポインタ変数があれば、ポインタ変数で他のタイプの変数を参照できるように、このポインタ変数で関数を呼び出すことができます.これらの概念は一致しています.関数ポインタには、関数の呼び出しと関数のパラメータの2つの用途があります.
関数ポインタ配列の定義方法については、2つあります.1つは標準的な方法です.一つはだまし方です.1つ目は標準メソッド:{解析:関数ポインタ配列は、その要素が関数ポインタの配列である.すなわち、このデータ構造は配列であり、その要素は関数エントリアドレスを指すポインタである.解析によると、まず、配列:配列名[]次に、その要素のデータ型ポインタ:*配列名[].また、各配列要素が関数のエントリアドレスを指すポインタであることを明らかにするには、関数戻り値タイプ(*配列名[])()である.ここではなぜ「*配列名[]」をカッコで拡張するのか注意してください.カッコと配列説明子の優先度は同じですので、カッコを使わずにポインタ配列説明式を拡張し、カッコと角カッコの結合方向に基づいて、*配列名[]()は何を説明しますか?は、エレメントの戻り値タイプがポインタの関数配列です.このような関数配列はありますか?わかりません.配列の各要素がポインタであることを保証するために、囲む必要があります.}2つ目は、関数は変数ではありませんが、ポインタ変数に割り当てることができるメモリに物理アドレスがあります.関数アドレスを取得する方法は、カッコとパラメータを持たない関数名で取得します.関数名は、その関数エントリを指すポインタ定数に相当します.では、関数名がポインタ定数である以上、強制タイプ変換などの対応する処理を行うことができます.では、このアドレスを整形ポインタ配列に配置し、関数ポインタとして呼び出すことができます.完全な例:
#include "stdio.h" 
int add1(int a1,int b1) 
{ 
	return a1+b1; 
} 
int add2(int a2,int b2) 
{ 
	return a2+b2; 
} 
int main() 
{ 
	int numa1=1,numb1=2; 
	int numa2=2,numb2=3; 
	int (*op[2])(int a,int b);//      
	op[0]=add1; 
	op[1]=add2; 
	printf("%d %d
",op[0](numa1,numb1),op[1](numa2,numb2)); }

関数ポインタ配列付与関数ポインタ配列付与には、静的定義と動的付与の2つの方法があります.  1. 静的定義関数ポインタ配列を定義するときに、各メンバーに対応する関数が決定されます.例えば、void(*INTARRAY[])(void)={Stop,Run,Jump}根本的には関数ポインタ配列は配列であるため,配列の定義と同様に静的付与であるため,[]の中の数字は省略できる.この関数ポインタ配列のメンバーは3つあります.               INTARRAY[1]();//Run関数2を実行する.動的割り当ては、必要に応じて値を割り当てる関数ポインタ配列を定義することもできます.本来の姿を復元するために、特定のタイプを実行する関数ポインタをタイプ再定義し、この新しいデータ型で配列を定義します.typedef void(*INTFUN);//このタイプの関数ポインタは、パラメータなし、戻り値なしの関数を指します.           INTFUN INTARRAY[32];//各メンバーがINTFUNタイプの関数ポインタINTARRAY[10]=INT_TIMER0;//INTARRAYを付与する[10];//呼び出し関数ポインタ配列の10番目のメンバーが指す関数