指针

来源:互联网 发布:python哪个版本好用 编辑:程序博客网 时间:2024/05/22 14:15

指针数组

即用于存储指针的数组,也就是数组元素都是指针  

       int* a[4]

表示:数组a中的元素都为int型指针元素表示:*a[i]  或 *(a[i])   ,因为[]优先级高于*

数组指针

即指向数组的指针 

int  (*a)[4]

表示:指向数组a的指针    元素表示:(*a)[i]

代码演示如下★★★

#include <iostream>

usingnamespacestd;

intmain()

{

int c[4]={1,2,3,4};

int* a[4];//指针数组

int  (*b)[4];//数组指针

b=&c; //b=c;

//将数组c中元素赋给数组a

for(int i=0;i<4;i++)

{

a[i]=&c[i];

}

//输出看下结果

cout<<*a[1]<<endl;//输出2就对

cout<<(*b)[2]<<endl;//输出3就对

return0;

}

注意:定义了数组指针,该指针指向这个数组的首地址,必须给指针指定一个地址,容易犯的错得就是,不给b地址,直接用(*b)[i]=c[i]给数组b中元素赋值,这时数组指针不知道指向哪里,调试时可能没错,但运行时肯定出现问题,使用指针时要注意这个问题。但为什么a就不用给他地址呢,a的元素是指针,实际上for循环内已经给数组a中元素指定地址了。但若在for循环内写*a[i]=c[i],这同样会出问题,相当于也是赋值,而不是给定指针地址。总之一句话,定义了指针一定要知道指针指向哪里,不然要悲剧。

指针函数

本质是一个函数,函数返回值是某一类型的指针。不加括号直接*

类型标识符    *函数名(参数表)

int                    *f(xy);

函数返回值必须用同类型的指针变量来接受,即指针函数一定有函数返回值,而且,在主调函数中,函数返回值必须赋给同类型的指针变量。

表示:

float *fun();

float *p;

p = fun(a);

         函数返回的是一个地址值,经常使用在返回数组的某一元素地址上。

 int * GetDate(int wk,int dy);
 main()
 {
 int wk,dy;
 do
 {
 printf(Enter week(1-5)day(1-7)\n);
 scanf(%d%d,&wk,&dy);
 }
 while(wk<1 || wk>5 || dy<1 || dy>7);
 printf(%d\n,*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];
 }
         子函数返回的是数组某元素的地址。输出的是这个地址里的值。

函数指针----即指向函数的指针变量,其本质是一个指针变量

数据类型 (*指针变量名)(函数参数列表)

这里数据类型就是函数返回值的类型。

int (*f) (int x); /* 声明一个函数指针 */

指向函数的指针包含了函数的入口地址,可以通过它来调用函数。 例如:void (*fptr)();

把函数的地址赋给函数指针,可以采用下面两种形式:
         fptr=Function;         

         或者   fptr=&Function;    取地址运算符&不是必需的,因为单单一个函数标识符标号就表示了它的地址。

如果是函数调用,还必须包含一个圆括号括起来的参数表。可以采用如下两种方式来通过指针调用函数:
         x=(*fptr)();      或者  x=fptr();  第二种格式看上去和函数调用无异。倾向于使用第一种格式,因为它明确指出是通过指针而非函数名来调用函数的。

下面举一个例子:
void (*funcp)();
void FileFunc(),EditFunc();

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

void FileFunc()
{

     printf(FileFunc\n);

}

void EditFunc()
{

     printf(EditFunc\n);

}
程序输出为:
 FileFunc
 EditFunc

1#include <stdio.h> 

2#include <stdlib.h> 

4 int max(int,int);  

5 int (*p)(int,int);  

6 int main()  

7  

8 int a,b,c;         

9 p = max;                           //使用方法  或者 p=&max;    因为函数名,就代表了它的地址

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

11 c = (*p)(a,b);                    //使用方法      或者c=p(a,b);                  第一种方法更能说明,是通过  函数指针  而非函数名 调用的函数

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

13 return 0

14

15

16int max(int x,int y) 

17

18    int z; 

19    if(x>y)

            z = x; 

20   else

            z = y; 

21   return(z); 

22}

  (2) int (* p) ( int,int ); 它只是定义一个指向函数的指针变量 p, 它不是固定指向哪一个函数的,而只是表示定义这样一个类型的变量,它是专门用来存放函数的入口地址的。在程序中把哪一函数(该函数的值应该是整形的,且有两个整形参数)的地址赋给它,他就指向哪一个函数。

  (3) p = max; 在给函数指针变量赋值时,只需给出函数名而不必给出函数参数,因为是将函数的入口地址赋给 而不涉及 实参和形参的结合问题,不能写成 p = max(a,b);

  (4) c = (*p)(a,b) 在函数调用时,只需将( *p ) 代替函数名即可,后面实参依旧。

  (5) 对于指向函数的指针变量,像 p++ ,p+n.....是无意义的。

指针的指针 

        例如char ** cp;如果有三个星号,那就是指针的指针的指针依次类推。当你熟悉了简单的例子以后,就可以应付复杂的情况了。当然,实际程序中,一般也只用到二级指针,三个星号不常见,更别说四个星号了。
char c='A';
char *p=&c;
char **cp=&p;  cp存储的值为p的地址;p存储的值为c的地址;c存储的值为A
    通过指针的指针,不仅可以访问它指向的指针,还可以访问它指向的指针所指向的数据。你可能想知道这样的结构有什么用。利用指针的指针可以允许被调用函数修改局部指针变量和处理指针数组。

 void FindCredit(int **);

 main()
 {
 int vals[]={7,6,5,-4,3,2,1,0};
 int  *fp=vals;
 FindCredit(&fp);  //参数为指针的指针
 printf(%d\n,*fp);
 }

 void FindCredit(int ** fpp) //&fp传递给函数后,fpp的值为fp的地址,*fpp的值为fp的值,即元素的地址
 {
 while(*fpp!=0)        //这里的0代表空指针
 if(**fpp<0) break;      //这里的0代表字符0
 else (*fpp)++;          //改变fp存储的值(即fp指针指向哪一个元素),用fp++不行啊?
 }
最后fp存储的值为 元素 -4的地址,输出 -4
  首先用一个数组的地址初始化指针fp,然后把该指针的地址作为实参传递给函数FindCredit()FindCredit()函数通过表达式**fpp间接地得到数组中的数据。为遍历数组以找到一个负值,FindCredit()函数进行自增运算的对象是调用者的指向数组的指针,而不是它自己的指向调用者指针的指针。语句(*fpp)++就是对形参指针指向的指针进行自增运算的。

指针数组的指针
    指针的指针另一用法是处理指针数组。有些程序员喜欢用指针数组来代替多维数组,一个常见的用法就是处理字符串。


 char *Names[]={
 Bill,
 Sam,
 Jim,
 Paul,
 Charles,
 0};   //普通数组 用"","",''将元素分割
      //因为这里是指针数组,所以这个0代表空指针
main()
{

 char **nm=Names;
 while(*nm!=0)

   printf(%s\n,*nm++);

}
   先用字符型指针数组Names的地址来初始化指针nm。每次printf()的调用都首先传递指针nm指向的字符型指针,然后对nm进行自增运算使其指向数组的下一个元素(还是指针)。注意完成上述认为的语法为*nm++,它首先取得指针指向的内容,然后使指针自增。就是先取地址,然后自加,不能*(nm++)
   注意数组中的最后一个元素被初始化为0while循环依此来判断是否到了数组末尾。具有零值的指针常常被用做循环数组的终止符。程序员称零值指针为空指针(NULL)。采用空指针作为终止符,在增删元素时,就不必改动遍历数组的代码,因为此时数组仍然以空指针作为结束。

用指向函数的指针作为函数参数

  函数指针变量通常的用途之一就是把指针作为参数传递到其他函数。

  函数的参数可以是变量、指向变量的指针变量、数组名、指向数组的指针变量,也可以是指向函数的指针也可以作为参数,以实现函数地址的传递,这样就能够在被调用的函数中使用实参函数。       int后面不能有形参名字 

     //返回整形数据的函数指针 xu  xu  xu 

void sub ( int ( *x1) (int), int (*x2) (int,int) )           //形参分别为指向有1个和2个整形参数的、返回整型数据的函数指针                       

    {

      int a,b,i,j;                           //这里的变量也可以是全局变量,或者 sub函数有返回值  xu xu xu

      a = (*x1)(i);      /* 调用 f1 函数 */

      b = (*x2)(i,j);                      /* 调用 f2 函数 */

    }

sub( (*x1),(*x2));    这样调用sub函数,只能将函数地址传递给sub函数,函数地址就是实参,如果需要给这两个函数传递参数,需要在sub函数定义时,再多定义形参,然后传递给这两个函数。  //这里的变量也可以是全局变量,或者 sub函数有返回值  xu xu xu

  如果实参为两个函数名 f1 和 f2. 在函数首部(形参定义)定义x1x2为函数指针变量,x1指向的函数有一个整形形参,x2指向的函数有两个形参。和 是函数f1 和 f2所要的参数。函数sub的形参 x1x2(指针变量)在函数 sub 未被调用时并不占用内存单元,也不指向任何函数。在sub被调用时,把实参函数 f1 和 f2的入口地址传给形式指针变量 x1 和 x2.

        既然在 sub 函数中要调用 f1 和 f2 函数,为什么不直接调用f1 和 f2而要用函数指针变量呢确实,如果只是用到f1 和 f2 函数,完全可以在sub函数中直接调用f1 和 f2,而不必设指针变量 x1 和 x2 但是,如果在每次调用sub时,调用的函数不是固定的,下次是f3 和 f4,再是f5 和 f6...这时用指针变量就比较方便了。(注意哪些元素可以作为函数参数!!!!!)

函数声明

int max(int ,int ); 

int max(int  a,int  b);   //都可以

函数定义:

int max(int h,int y)      //但定义时,int后的形参名字不能省略

{     

    int x=0;

    int z; 

    if(x>y) 

       z = x;

    else

        z = y; 

    return(z);

}



0 0