ポインタ関数と関数ポインタの違い


一、
1、ポインタ関数とは、ポインタ付きの関数、すなわち本質が関数である.関数の戻りタイプは、あるタイプのポインタです.
タイプ識別子*関数名(パラメータテーブル)
     
 int *f(x,y);

まず関数です
あ、ただし、この関数の戻り値はアドレス値です.関数の戻り値は、同じタイプのポインタ変数で受け入れなければなりません.つまり、ポインタ関数には必ず関数の戻り値があります.また、プライマリコール関数では、関数の戻り値は同じタイプのポインタ変数に割り当てなければなりません.
表示:
float *fun();

float *p;

p = fun(a);

注意ポインタ関数と関数ポインタの表現方法の違いは、決して混同しないでください.
最も簡単な判別方法は、関数名の前のポインタ*番号が括弧()に含まれているかどうかを見ることであり、含まれている場合は関数ポインタであり、逆にポインタ関数である.
ポインタ関数:
関数が戻り値をポインタとして宣言すると、ポインタまたはアドレスを必要とする式で使用するために、実際には呼び出し関数にアドレスが返されます.
書式:
       
タイプ説明子*関数名(パラメータ)
もちろん、返されるアドレスは1つなので、タイプ説明子はintが一般的です.
    
  :int *GetDate();
int * aaa(int,int);

関数は、返される配列の要素アドレスによく使用されるアドレス値を返します.
 
int * GetDate(int wk,int dy);
main()
{
            int wk,dy;
            do
            {
                printf(Enter week(1-5)day(1-7)
); scanf(%d%d,&wk,&dy); } while(wk<1||wk>5||dy<1||dy>7); printf(%d
,*GetDate(wk,dy)); } int * GetDate(int wk,int dy) { static int calendar[5][7]= { {1,2,3,4,5,6,7}, {8,9,10,11,12,13,14}, {15,16,17,18,19,20,21}, {22,23,24,25,26,27,28}, {29,30,31,-1} }; return &calendar[wk-1][dy-1]; }

プログラムはよく理解されるべきで、サブ関数は配列のある要素のアドレスを返します.出力はこのアドレスの値です.
2、
関数ポインタは、関数を指すポインタ変数、すなわち本質がポインタ変数である.

int (*f) (int x); /*          */
f=func; /*  func          f */

関数を指すポインタには、関数のアドレスが含まれており、関数を呼び出すことができます.宣言形式は次のとおりです.
            (*   )(  )

実はここでは関数名とは言えません.ポインタの変数名と呼ぶべきです.この特殊なポインタは、整数値を返す関数を指します.ポインタの宣言削りは、関数を指す宣言と一致します.
ポインタ名とポインタ演算子の外側のカッコは、デフォルトの演算子の優先度を変更します.カッコがない場合は、整数ポインタを返す関数のプロトタイプ宣言になります.
例:
void (*fptr)();

関数のアドレスを関数ポインタに割り当てるには、次の2つの形式があります.

fptr=&Function;
fptr=Function;

   
アドレス演算子&は必須ではありません.1つの関数識別子だけがアドレスを示すため、関数呼び出しの場合はカッコで囲まれたパラメータテーブルも含まなければなりません.
(ここに注意)
ポインタで関数を呼び出すには、次の2つの方法があります.

x=(*fptr)();
x=fptr();

2つ目のフォーマットは、関数呼び出しと変わらないように見えます.しかし、一部のプログラマーは、関数名ではなくポインタによって関数を呼び出すことを明確に示すため、最初のフォーマットを使用する傾向があります.次に例を示します.

void (*funcp)();
void FileFunc(),EditFunc();

main()
{
            funcp=FileFunc;
            (*funcp)();
            funcp=EditFunc;
            (*funcp)();
}

void FileFunc()
{
            printf("FileFunc
"); } void EditFunc() { printf("EditFunc
"); }

プログラム出力:
            FileFunc
            EditFunc
主な違いはポインタ変数であり、関数である.正しく使うには、はっきりさせる必要があります.
二、
針の針
ポインタのポインタは少しわかりにくいように見えます.それらの宣言には2つの星があります.例:
char ** cp;

nginxのコードに***とかあるのを思い出す
例えばngx_event.c(890):

static char *
ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    char                 *rv;
    void               ***ctx;
    ngx_uint_t            i;
    ngx_conf_t            pcf;
    ngx_event_module_t   *m;

三つの星があれば、それは針の針の針で、四つの星は針の針の針の針で、順番に類推します.簡単な例を熟知すれば、複雑な状況に対処することができます.
ポインタのポインタにはポインタのアドレスが必要です.
       
char c='A';
char *p=&c;
char **cp=&p;

ポインタのポインタにより、ポインタが指すポインタだけでなく、ポインタが指すデータにもアクセスできます.次の例をいくつか示します.

char *p1=*cp;
char c1=**cp;

このような構造が何の役に立つか知りたいかもしれません.
ポインタのポインタを使用すると、呼び出された関数によってローカルポインタ変数を変更し、ポインタ配列を処理できます.
 
void FindCredit(int **);
main()
{
            int vals[]={7,6,5,-4,3,2,1,0};
            int *fp=vals;
            FindCredit(&fp);
            printf(%d
,*fp); } void FindCredit(int ** fpp) { while(**fpp!=0) if(**fpp<0) break; else (*fpp)++; }

まずポインタfpを1つの配列のアドレスで初期化し,そのポインタのアドレスを実パラメータとして関数FindCredit()に渡す.FindCredit()関数は式**fppによって間接的に配列中のデータを得る.配列を巡回して負の値を見つけるために、FindCredit()関数が自己加算するオブジェクトは、呼び出し元の配列を指すポインタであり、呼び出し元のポインタを指すポインタではありません.文(*fpp)++は、パラメータポインタが指すポインタを自己加算します.ただし、*演算子は++演算子より高いため、カッコはここで必須であり、カッコがない場合、++演算子は二重ポインタfppに作用します.
三、
ポインタ配列へのポインタ
ポインタのポインタのもう一つの使い方は、ポインタ配列を古い処理で処理します.いくつかのプログラマーは、多次元配列の代わりにポインタ配列を使用するのが好きで、文字列を処理するのが一般的です.
 
char *Names[]=
{
             Bill,
             Sam,
             Jim,
             Paul,
             Charles,
             0
};
 main()
{
            char **nm=Names;
            while(*nm!=0) printf(%s
,*nm++); }

ポインタnmは、まず文字型ポインタ配列Namesのアドレスで初期化される.printf()の呼び出しのたびに、ポインタnmが指す文字型ポインタが最初に伝達され、その後、nmが配列の次の要素(またはポインタ)を指すように自己増幅演算される.注意上記のように考えられる構文は*nm++であり、まずポインタが指す内容を取得し、その後ポインタを自己増加させる.
注意配列の最後の要素は0に初期化され、whileループは配列の最後になったかどうかを判断します.ゼロ値を持つポインタは、ループ配列の終端としてよく使用されます.プログラマはゼロ値ポインタを空ポインタ(NULL)と呼ぶ.空のポインタを終端として使用すると、ツリーが要素を削除するときに、配列を巡るコードを変更する必要はありません.このとき、配列は空のポインタで終了します.
リファレンスhttp://www.cnblogs.com/gmh915/archive/2010/06/11/1756067.html