zoukankan      html  css  js  c++  java
  • 指针深入分析

     

    指针学习资料(zollty-2009)

    1.指向普通变量或者某个数或者字符串。例如

    int j,a[10];

    int *pointer_1,*pointer_2;

    pointer_1=&j;

    pointer_2=&a[7];

     

    2.指针作为函数参数。例如

     (主函数部分)

    pointer_1=&a;pointer_2=&b;

    if(a<b) swap(pointer_1,pointer_2);

    (交换两数的函数)

    void swap(int *p1,int *p2)

    { int temp;

      temp=*p1;

      *p1=*p2;

      *p2=temp;

    }

    swap接受主函数传来的两个数a和b的地址,用p1和p2去指代,然后交换p1和p2的内容,则在内存上引起了改变,所以原来的a和b所对应的值改变。

     

    3.指向数组首地址【例1】

    对于一维数组:p=a; 调用:*(a+i)或者*(p+i)

    对于二维数组:p=a[0]; 调用:*(a[0]+i)或者*(p+i)

     

    4.指向数组的每行【例2】

    形如:

    int a[3][4];

    int (*p)[4]; p=a;

    调用:*(*(p+i)+j)

     

    5. 指向函数。例如

    int max(int x,int y);

    n=max(a,b);

    可以改作:

    int (*p)(int,int);

    p=max;

    n=p(a,b);

     

    6.返回指针值的函数。例如

    int *a(int x,int y);

     

    7.指针数组。【例3】

    它是一个数组,例如

    int *p[4];

    char *name[]={"BASIC","C++","PASCAL","COBOL","SQL"};

     

    8.指向指针的指针【例4】

    形如 char **p;

     

    9.指针的运算

    (1)减法:如果两个指针指向同一数组,则两个指针之差为它们之间间隔的元素个数,比如p1指向a[1],p2指向a[4],则p2-p1=3。而p1+p2无意义;

    (2)比较,>、<、=,比较的是同一数组中的元素的先后顺序;

    (3)赋值,同类型的指针才能相互赋值,若p1为int型,p2为float型,则可以强制转换p1=(int *)p2;

    (4)可以令p=NULL,即使指针指向地址为0的单元,因为指针在未赋值以前指向的是一个未知的地址,这是非常危险的,所以不妨在引用它以前就把NULL赋值给它。

     

    【例】

     

    1.普通指针指向多维数组

    #include <iostream>

    using namespace std;

    int main()

    { int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};

      int *p;

      for(p=a[0];p<a[0]+12;)     //a[0]代表数组a[3][4]的首地址,而a代表的是数组第一行的首地址,所以指针a与指针a[0]不同.

             cout<<*p++<<" ";

      cout<<endl;

      return 0;

    }

     

    2.行指针指向多位数组

    形如(*p)[10],用法为*(*(p+i)+j)

    #include <iostream>

    using namespace std;

    int main()

    { int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};

      int (*p)[4],i,j;

      cin>>i>>j;

      p=a;                         //a代表的是数组第一行的首地址.

      cout<<*(*(p+i)+j)<<endl;

      return 0;

    }

     

    3.用来装字符串的数组

    方法一:(指针法)

    #include <iostream>

    using namespace std;

    int main()

    { char *name[]={"BASIC","C++","PASCAL","COBOL","SQL"};

      cout<<name[0]<<endl;

      return 0;

    注意:输出的时候用的是name[0]而不是name或者*name[0],后面(例4)将说明原因。

    }

    方法二:(字符数组法)

    #include <iostream>

    using namespace std;

    int main()

    { char name[][30]={"BASIC","C++","PASCAL","COBOL","SQL"};

      cout<<name[0]<<endl;

      return 0;

    }

    注意:方法二不适合类似于int a[2][3]={{5,8,6},{3,2,4}};的数组(此时若想输出a[0]则是错误的做法)。

     

    方法三:(字符串数组法)

    #include <iostream>

    #include <string>

    using namespace std;

    int main()

    { string name[]={"BASIC","C++","PASCAL","COBOL","SQL"};

      cout<<name[0]<<endl;

      return 0;

    }

     

    4.

    #include <iostream>

    using namespace std;

    int main()

    { char **p;

      char *name[]={"BASIC","PASCAL","C++","COBOL","SQL"};

      p=name+2;

      cout<<*p<<endl;

      cout<<**p<<endl;

      return 0;

    }

    分析:*p=name[2]= "C++"的首地址,(通常所说一个字符串的“地址”实际上指的是它的“首地址”或者“起始地址”),用cout 输出的不是字符串的首地址而是整个字符串(只要把一个字符串的起始地址给它,cout就一直往后面输出,直到遇到结束符'\0'为止),

    为了证明这一点,请看:string a=“finish”;cout<<a<<endl;变量a中只是存放的“finish”的首地址,但是用cout却是把整个“finish”字符串全部输出。故:

    例4,第一个*p输出"C++",第二个**p代表"C++"首地址的内容,即C。

    例3中,name[0]为"BASIC"的首地址,输出"BASIC",若换成*name[0]则输出B,若换成name则代表的是整个数组的首地址(而不是单个字符串"BASIC"的地址),所以此时输出的是整个数组的首地址。若用*name则输出整个数组的首地址的内容,即"BASIC"(可见字符串的首地址内容为单个字符,一维数组首地址的内容为它的第一个元素,对于二维数组,比如a[3][4],a代表的是第一行的地址,所以cout<<a输出第一行的地址,而cout<<*a则是错误的用法,因为不可能将第一行的所有元素全部输出,提醒:注意一维数组和二维数组的区别)。

  • 相关阅读:
    实现继承的几种方式
    使用 + 操作符、parseInt 、 parseFloat等方法处理数字字符串时的不同
    jQuery插件版无缝轮播,重写了之前的代码,显得更高大上一点
    我是如何从零开始构建一个jsp项目的
    css居中方法详解
    嫌innerHTML性能不够好,推荐几个新方法
    初学事件委托
    Set集合——HashSet、TreeSet、LinkedHashSet(2015年07月06日)
    十大Intellij IDEA快捷键(转)(2015年06月15日)
    IntelliJ IDEA 集成Tomcat后找不到HttpServlet问题(2015年06月13日)
  • 原文地址:https://www.cnblogs.com/zollty/p/2879309.html
Copyright © 2011-2022 走看看