C/C++指针

2019-09-20  本文已影响0人  LogyKoala
  1. 概念
    一个变量的指针就是该变量的地址,用来存放指针的变量就是指针变量。
    *指针运算符,也叫间接访问运算符 。
    &取指针运算符,也叫地址运算符。

  2. 指针与地址的区别
    指针有类型,地址没有类型,需要强制类型转换才能够赋值给指针变量

  3. 为什么指针会有类型
    因为指针存储的是一个内存地址,然而我们根据内存地址读取与之相对应的数据,但是在读取的过程中不知道什么时候读取完毕,所以我们需要类型,来确定什么时候读取完毕
    eg:char 2字节 16位。 int 4字节 32位

  4. 变量与指针

    • 定义指针变量
       //数据类型* 指针变量名;
       int* p;
      
      地址是对一段数据的描述
      变量名是对内存的一段空间里的数据都抽象描述
    • 初始化
      //指针变量名 =&变量名;
      int a =25;
      int* p;
      p =&a;
      //&p 代表取地址
      //*p 代表取值
      
      &a 是变量a的地址(地址)
      *p 是指针变量指向的内存单元(内存单元)
    • 根据地址拿值
      int a =25;
      //取地址 
      &a;
      //根据地址拿具体值
      *(&a);
      
    • 指针作为函数参数
      void my(int * p1){}
      //调用
      my(p1);
      //或者
      int a =10;
      my(&a);
      
  5. 空指针

    • 指针变量可以为空,也就是说该指针变量不指向任何变量
      int *p =NULL;//如果不使用,一定要这样写
      p=NULL;
      //系统已经定义NULL #define NULL 0,p指针指向地址为0的单元,使指针不指向任何有效单元。
      //指针为空和指针未赋值是两个概念,前者有值(为0)不指向任何变量。
      //后者虽然未赋值但不代表它无值,而是一个无法预料的值,可能会指向一个未指定的单元,这种情况很危险
      
  6. 指针变量的数据类型

    int i; //定义整型变量
    int* p; //p是指向整形数据的指针变量
    int a[n]; //定义整型数组a,a中有n个元素
    int* p[n];  //定义指针数组p,由n个指向整形数据的指针元素组成
    int (*p)[n]; //p是指向含n个元素的一维数组的指针变量
    int f (){}; //返回值是int类型,名叫f的函数
    int* p(){}; //返回值是指针的,叫做p的函数,该指针指向整形数据
    int (*p) (){}; //p是指向函数的指针,该函数返回一个整形
    int * * p; //p是指向指针的指针变量,它指向一个指向整型数据的指针
    
  7. 数组与指针

    • 指向数组元素的指针
      1. 在C++中数组名,数组名代表数组中第一个元素的地址
      int a[10];
      int *p;
      p =&a[0]; //或者。 p=a;
      
    • 用指针变量做函数参数接收数组地址
      void my(int array[]);
      void my(int* array);
      以上两种写法完全等价
    • 数组在内存中的排列是连续不断的(线性排列)
    • 二维数组
      int ids[2][3] ={10,20,30,40,50,60};
      ids;//代表一个行指针,指向一个有三个元素的素组,大小是3*4=12
      &ids;//代表整个二维数组的指针,大小是2*3*4 =24
      *ids;//代表的是一个指向该二维数组的数据类型的指针,相当于ids首地址&ids[0][0]
      
      推导 ids[1][1] =* ( *(ids+1)+2);
      1. 第一步
      //    ids代表第一行        第一行的第一个指针 *ids
      //    ida+1 代表下一行   第二行的第一个指针 *(ids+1)
      //    以此类推第n行第一个指针 *(ids+n)    
      
      1. 第二步
      //    取每i行第一个元素的指针  :*(ids+i)
      //    取第一行第二个值 *ids+1
      
      1. 第三步
      //取第二行第二个元素的指针 *(ids+1)+1
      //取第i行第j个元素的指针 *(ids+i)+j
      //获取指针变量的值*(*(ids+i)+j)
      
  8. 函数与指针

    • 定义
      函数在编译时被分配一个入口地址,这个函数的入口地址就被称为函数的指针
    • 用函数指针变量调用函数
      //定义函数
      int max(int x, int y);
      int (*p)(int ,int);
      p =max;
      int m =p(1,2);
      //以上代码就将max的入口地址赋给了指针变量p,函数名            代表的是函数的入口地址
      //注意不能写 p =max(1,2);  max(1,2);这种写法为函数调用
      
    • 用指向函数的指针做函数的参数
      int my_max(int x, int y,int (*p)(int ,int));
      //调用
      int max(int x, int y);
      my_max(50,60,max)
      
    • 返回指针值的函数
      int* p(int x, int y);
      
    • 指向指针的指针(二级指针)
      指针变量也是变量,同样会占据内存空间,同样有地址,因此我们就可以用一个指针指向它,我们就称之为二级指针
      多级指针的作用:删除链表,动态分配内存给二维数组...
      int* p =NULL;
      int a =1;
      p =&a;
      int **t =NULL;
      t =&p;
      //**t == 1;
      
  9. 指针的运算

    • 指针变量的赋值

      p=&a; //将变量a的地址赋给p
      p=array;//将数组array的首个元素的地址赋给p
      p=&array[i]; //将数组array的i个元素的地址赋给p
      p=max; //将函数max的入口地址赋给p
      p=p1; //p和p1需要都是同类型的指针变量,将p1的值赋给p
      
    • 指针变量赋值时注意
      一般情况下,我们不会直接给指针变量赋值为整数,原因是因为数字比较小,系统本身已经占用了这块内存区域,系统本身的内存数据是不允许被访问的

    • 指针变量加/减一个整数
      指针++,每次想起移动sizeof(数据类型)个字节

      int *p; //地址为001FFAB4
      p++;//地址为001FFAB8 int类型为4字节
      
       //  使用,通过指针遍历数组元素
       int ids[] ={10,20,30,40,50,60};
       int *p =ids;
       for(;p<ids+6;p++){
            *p;
       }
      
       //通过指针的方式给数组赋值
       int ids[6];
       int* p =ids;
       int i=0;
       for(; p< ids+6;p++){
           *p =i;
           i++;
       }
      

      让指针递增或者递减,只有在数组遍历的时候才有意义,基于数组在内存中是线性排列的方式,有可能会导致访问到其他的内存区。

    • 数组内部指针的加减

      int ids[] ={23,15,30,44,60};
      int* p =ids;
      p =p+3
      //*p =44;
      p =p-2
      //*p =15
      
    • 两个指针变量比较
      指针大小比较:一般都是在数组遍历的时候使用,一般情况下没什么用
      指针相等比较:指针地址相等,并不代表值相等,因为指针有类型
      如果两个指针变量指向同一个数组元素,指向前面元素的指针变量小于指向后面元素的指针变量

上一篇 下一篇

猜你喜欢

热点阅读