小李指针初体验( •̀ ω •́ )y

指针变量

  1. 指针:本质上就是地址;
  2. 指针变量:存放一个变量地址的变量;
  3. 定义指针变量:类型名 * 指针变量名;类型名即基类型,用来确定所占内存,便于±1;
  4. 在定义时初始化:int * p=&a;
  5. 不能把整数赋给指针变量;
  6. 引用指针:
    • 赋值:p=&a;或*p=1;(后者要求p已经有所指向,不能未初始化)
    • & 取地址运算符,&a,表示a的地址;
      • 指针运算符,*p,表示p所指对象;
  7. 指针变量作函数参数
    • 注意!!!不要试图改变指针形参的值来改变实参
    • 要改变指针形参所指向的值来改变实参
    • ✔’‘‘void swap(int * p1,int * p2)
      {
      int temp;
      temp=*p1;
      *p1=*p2;
      *p2=temp;
      }’’’
      ❌’‘‘void swap(int * p1,int * p2)
      {
      int * p;
      p=p1;
      p1=p2;
      p2=p;
      }’’'(形参p1,p2的值无法传回实参,所以失败)

通过指针引用数组

  1. 数组元素的指针:
    • 数组名代表数组首地址;
    • 把首地址赋给指针变量:p=&a[0];或 p=a;
    • 引用数组:①下标法 ②指针法(good)
  2. 用指针引用数组
    1. 此时指针的运算:
      • p++;p–; 这里的+1是指向数组下一个元素;
      • 并不是简单+1,而是加上数组元素所占字节,这就要指针的基类型了;
      • p1-p2,当指针指向同一数组有意义,用来计算相对距离,(p1-p2)/一个数组元素所占字节;
    2. 若p一开始指向a[0],* (p+i) = * (a+i) = a[i];
      []实际上是变址运算符,即a[i]按照a+i计算地址;
    3. 直接用指针引用数组快;
      ‘’‘for(p=a;p<(a+10);++p)
      printf(“%d”,*p);’‘’
      虽然a也是地址,但为常量,不能a++;
    4. 指针指向数组时可以带下标,p[i]=*(p+i);建议少用
      • p++ 等价于 *(p++);
    5. ++(*p)是指数组元素值加1,而不是地址;
  3. 用数组名作函数参数
    • 定义的时候要注意arr[],括号!!!;
    • 调用时候光写数组名!!没有[]
    • 用数组名作参数时,形参中元素变化,实参也变;
    • 用数组元素做形参和变量一样,只是值传递;
    • 实参数组名代表一个固定地址(指针常量),但形参数组名按指针变量处理(地址不固定);
  4. 多维数组元素地址
    • a代表首行首地址,a+1代表行号为1的首地址
    • a[1]和 * (a+1)等价,*&a[1] [2]=a[1]+2= (a+1)+2
      • (a+i) ==a[i]; * (a[i]+j) == * (*(a+i)+j);
    • 在指向行的指针前面加一个*,就转化成指向列的指针;
    • 在指向列的指针前加&,转为指向行的
    • &a[i]和a[i]值一样,但是含义不同,前者&a[i] 或 a+i指向行,后者a[i] or *(a+i)指向列
    • 在二维数组中,a+i == a[i] == *(a+i) == &a[i] == &a[i][0],值相同
  5. 指向多维数组的指针变量
    1. 指向数组元素的指针变量
      1. 二维数组的元素在内存中按序存放,因此可以用一个指向整型元素的指针,依次指向各元素;
      2. ‘’’
        int a[3][4] = { 1,2,3,4,5,6,7,8,9,0,11,21 };
        int* p;
        for (p = a[0];p < a[0] + 12;++p)
        //注意!!!不能p=a,p是int * 型2,a是int(*)[4]型(指向一维中有四位元素的一维数组)
        {
        if ((p - a[0]) % 4 == 0) printf(“\n”);
        // 地址之差用于判断相对距离
        printf(“%4d”, *p);
        }‘’’
      3. a[i][j]在数组中的相对位置,i* m+j(数组大小n*m)
      4. a[i][j]的地址&a[0][0]+(i* m+j) or p+(i*m+j);
        2.指向由m个元素组成的一维数组的指针变量
      5. 定义指针:int (*p) [4];指向包含四个整型变量的一维数组,注意()括号,若缺少括号,就是指针数组;
      6. 让p指向一维数组:p=a;(a是二维数组时) or p=&a;(a是一维数组时)
      7. int a[3][4]; int (* p) [4];p=a;(p+2)+3)表示a[2][3];
  6. 用指向数组的指针作函数参数
    注意 类型!!! 要匹配
    • void average(float* p,int n );//定义的时候p是指向元素的指针
      average(* score,12);//score是二维数组,调用的时候,实参一定要和赋值时一样的形式,或*score,或score[0],或&a[0][0]
    • void search(float(* p)[4],int n);
      search(score,2);

通过指针引用字符串

  1. 定义指针:const char * string=“i love you”;
    //注意const ,字符串是常量,类型要一致;
  2. 输出字符串(用指针):printf(“%s”,string);//类字符数组,在这放地址就行,遇到’\0’停止
  3. 可以对指向字符串的指针变量再赋值,改变他所指的串,但字符数组错过初始化就不能再整体赋值了
  4. 注意!!复制或者怎么得来的像字符串的,一定要注意最后有没有’\0’,需不需要额外添加一个
  5. 字符指针作函数参数:函数的实参和形参可以分别用字符数组名和字符指针变量,只要参数的本质是地址即可
    eg.定义的时候void copy_ string(char from[],char to[]);
    调用的时候可以用指针copy_string(a,b);//这里a 和b是先前定义的指针;
    调用的时候也可以是数组名copy_string(from,to);
  6. while((* to++ = * from++)!=‘\0’);等价于while(* to++ = * from ++);
  7. 字符指针变量和字符数组的比较
    • 赋值方式:可以对指针变赋值,但不能对数组名赋值;
    • 指针变量的值可以改变,但数组名代表一个固定的地址
    • 字符数组中各元素的值可以改变,但字符指针指向的字符串常量的内容不可以改;
    • 用指针变量指向一个格式字符串,可以用他代替printf中的格式字符串;eg.‘’’
      const char * format;
      format=“a=%d,b=%f\n”;
      printf(format,a,b);‘’’
      等价于printf(“a=%d,b=%f\n”,a,b);
      只要改变format所指向的字符串,就可以改变输入输出格式,这种printf函数称为可变格式输出函数;
      也可以用字符数组实现,但是错过初始化之后只能单独赋值,改变比较麻烦,所以用指针变量方便;
  8. 注意一定不要忘记让指针有所指向

指向函数的指针

  1. int (* p) (int,int);表示p指向函数类型为整型且有两个整型参数的函数,p的类型:int(*)(int,int)
  2. 通过指针变量访问他所指向的函数
    • ‘’‘int max(int,int);//函数声明
      int (*p)(int,int);//定义指向函数的指针
      int a,b,c;
      p=max;//让p指向max函数
      c=(*p)(a,b); //函数调用,这里等价于max(a,b); ‘’’
    • 不要忘记括号(),若int * p(int,int);就变成了返回值为指向整型变量指针的函数
  3. 定义和使用
    • 一个指针变量可以先后指向同类型的不同变量
    • 对指向函数的指针不能进行算术运算;
    • 虽然用指针调用函数不如用函数名调用的快,但是指针变量调用函数比较灵活
      eg.当有选择时,可以用一个指针变量调用不同选择下的不同函数;‘’‘int (*p)(int,int);
      if(n1) p=max;
      else if(n
      2) p=min;
      else if(n==3) p=add;
      c=(*p)(a,b);//调用p指向的函数
      printf(“%d”,c);’‘’
  4. 用指向函数的指针作函数参数
    • 示意’''void fun(int x,int y,int(*p)(int,int));
      if(n1) fun(a,b,max);
      else if(n
      2) fun(a,b,min);
      else if (n==3) fun(a,b,add);

//定义fun函数
void fun(int x,int y,int(*p)(int,int))
{
peintf(“%d\n”,(*p)(x,y));
}
//分别定义max,min,add函数 ‘’’

#返回指针值的函数

  1. 定义:类型名 * 函数名(参数)
  2. 例题:3名学生,4科成绩,输入序号,输出学生全部成绩
    思路:用二维数组放成绩,一个返回指针的函数
    简单示意:‘’’
    float * search(float(p)[4],int n);
    float * p;
    p=search(scare,k);//arr score,num k
    for(i=0;i<4;++i)
    printf(“%5.2f\t”,
    (p+i));
    //定义函数
    float * search(float(*p)[4],int n)
    {
    return *(p+n);//在指向一维数组的指针上加减,就是在行上蹦跶
    }‘’’

#指针数组和多重指针

  1. 指针数组
    1. 一个数组,若其元素均为指针类型数据,成为指针数组;
    2. 定义:类型名 * 数组名[数组长度];
    3. 指针数组可以指向若干字符串,同二维数组也可以解决,但是按照最长的字符串来定义列会浪费很多内存单元;
    4. 存放:const * name[]={“abc”,“bhj”,“jadoif”};
    5. 若想进行排序,不是移动字符串,而是改变指针数组各元素指向’‘‘void sort(const char* name[], int n)
      {
      const char* temp;
      int i, j,k;
      for (i = 0;i < n-1;++i)
      {
      k = i;
      for (j = i + 1;j < n;++j)
      {
      if (strcmp(name[k], name[j]) > 0) k = j;
      }
      if (k != i)
      {
      temp = name[i];
      name[i] = name[k];
      name[k] = temp;
      }
      }
      }’’'//strcmp(,)的参数是地址,对一维字符数组a,b,比较就是strcmp(a,b);
  2. 指向指针数据的指针
    1. 定义:char ** p;
    2. 使用:‘’‘const char* name[] = { “follow me”,“basoc”,“great”,“abc”,“good” };
      const char** p;
      int i;
      for (i = 0;i < 5;++i)
      {
      p = name + i;
      printf(“%s\n”, *p);
      }’‘’

引用

  1. 引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。其格式为:类型 &引用变量名 = 已定义过的变量名
  2. 特点:①一个变量可取多个别名。
    ②引用必须初始化。
    ③引用只能在初始化的时候引用一次 ,不能更改为转而引用其他变量。
  3. 引用作为参数
    • void swap(int &p1, int &p2) //此处函数的形参p1, p2都是引用
      { int p; p=p1; p1=p2; p2=p; }
      调用的时候直接swap(a,b);就可以交换
      使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作
  4. 常引用
    • const 类型标识符 &引用名=目标变量名
    • 用这种方式声明的引用,不能通过引用对目标变量的值进行修改,从而使引用的目标成为const,达到了引用的安全性。
      ‘’‘int a ;
      const int &ra=a;
      ra=1; //错误
      a=1; //正确’‘’
  5. 引用作为返回值
    • 类型标识符 &函数名(形参列表及类型说明)
      {函数体}
    • 用引用返回一个函数值的最大好处是,在内存中不产生被返回值的副本
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值