原创 C指针温习(五):指向函数、数组和指针的指针

2007-12-29 11:24 5814 7 7 分类: MCU/ 嵌入式

指向函数的指针


  我们知道,一个指针变量可以指向整型变量,字符串,数组,也可以指向一个函数。一个函数在编译的时候被分配给一个入口地址,这个入口地址就称为函数的指针。可以用一个指针变量指向函数,然后通过指针变量调用这个函数。因为每个函数都占有一段内存单元,它们有一个起始地址。所以,我们可以用一个指针变量指向一个函数,通过指针变量来访问它指向的函数。


如:


#include "stdio.h"


main()


{


    int max( int,int );


    int (* p)();


    int a,b,c;


    p = max;


    scanf( "%d,%d",&a,&b );


    c = (* p)(a,b);


    printf( "a = %d,b = %d,max = %d",a,b,c );


    getch();


}


<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 


max( int x,int y )


{


    int z;


    if( x>y )z = x;


    else z = y;


    return(z);


}


我们看到,其中int (* p)();首先,p*结合,表明了p是一个指针变量,后面的括号表明指针是指向函数的。 int表明了此函数带回了整型的返回值


赋值语句“p = max;”的作用是将函数max 的入口地址赋给指针变量p。和数组名代表数组起始地址一样,函数名代表该函数的入口地址。也就是说,pmax都指向函数的开头。值得注意的是,p是指向函数的指针变量,它只能指向函数的入口处,而不能指向函数中间的某一条指令处,因此不能用*p+1)来表示下一个指令。


这里说明一下,


(1)       指向函数的指针变量的一般形式为:


数据类型   * 指针变量名 )();


数据类型指的是函数返回值的类型。


(2)       函数的调用可以通过函数名调用,也可以通过函数指针调用。


(3)          *p)()表示定义一个指向函数的指针变量,它不固定指向哪一个函数,而只是表示定义了这样一个类型的变量,它是专门用来存入函数的入口地址的。要调用的时候,程序把哪一个函数的地址赋给它,它就指向哪一个函数。也就是说,一个指针变量可以先后指向返回类型相同的不同函数。


(4)          在给函数指针变量赋值时,只需要给出函数名而不必给出参数。如:


P = max;


因为是将函数入口地址赋给p,而不牵涉到实参与形参的结合问题。不能写成“p = max(a,b)”形式。


(5)          在函数指针变量调用时,只需要将(*p)代替函数名即可。在(*p)后的括号中根据需要写上实参。如下面程序表示:“调用由p指向的函数,实参为a,b。得到的函数值赋给c。”


c = (* p)(a,b);


(6)对于指向函数的指针变量像p++,p—等运算是无意义的。


 


                指针数组和指向指针的指针


一个数组,其元素均为指针类型数据,称为指针数组。也就是说,指针数组中的每一个元素都相当于一个指针变量。一维指针数组的定义形式为:


类型名    * 数组名[数组长度]


例如:  int * p[22]


P先与[4]结合,形成p[22]的形式,就显然是数组形式,它有四个元素,然后再与p前面的“*”结合,“*”表示此数组是指针类型的,每个数组元素(相当于一个指针变量)都可以指向一个整型变量。


为什么要用到指针数组呢?它比较适合于用来指向若干个字符串,使字符串处理起来更加方便。也会节省更多的内存单元。


比如:分别定义一些字符串,然后用指针数组中的元素分别指向各字符串,如果想对字符串排序,不必屐字符串的位置,只需要改变指针数组中各元素的指向(即改变各元素的值,这些值是各字符串的首地址),这样,各字符串的长度可以不同,而且移动指针变量的值(地址)会比移动字符串所花的时间少得多。


比如:


#include


#include


 


void main()


{


    void sort( char *name[],int n );


    void print( char * name[],int n );


    char * name[] = { "Follow me","BASIC","Great Wall","FORTRAN","Computer"};


    int n = 5;


    sort( name,n );


    print( name,n );


    getch();


}


 


void sort( char * name[],int n )       //对书排序


{


    char * temp;


    int i,j,k;


    for( i = 0;i


    {


        k = i;


        for( j = i+1;j


            if(strcmp( name[k],name[j])>0)k = j;


        if( k!=i )


            {temp = name;name = name[k];name[k] = temp;}


    }


}


 


void print( char * name[],int n )       //打印出来


{


    int i = 0;


    char * p;


    p = name[0];


    while(i


    {


        p = *(name+i++);


        printf("%s\n",p);


    }


}


 


指向指针的指针:


怎么样定义一个指向指针数据的指针变量呢?例如:


char **p


因为*运算符的结合性是从右向左,所以它相当于:**p),显然,(*p)是指针变量的定义形式,如果没有前面的*,那就是定义了一个指向字符数据的指针变量,现在它前面又多了一个*,表示指针变量p指向一个字符指针变量的。(*p)是p指向的另一个指针变量。


例:


void main()


{


    char * name[] = { "Follow me","BASIC","Great Wall","FORTRAN","Computer"};


    char **p;


    int i;


    for( i = 0;i<5;i++)


    {


        p = name + i;


        printf("%s\n",*p);


    }


    getch();


}


我们知道,在赋值的时候,p = name + i;是指p指向指针数组的第i行,加一个*后,*p是指向数组的第i行第0列的首地址,再加一个*后, **p指向第i行第0列地址中的内容。这个就比较好理解了。

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
7
关闭 站长推荐上一条 /3 下一条