美文网首页
[C语言] 想学会用指针吗?

[C语言] 想学会用指针吗?

作者: 入梦瞌睡 | 来源:发表于2019-08-03 23:28 被阅读0次

    目录

    1.本文主要内容

    2.基础知识讲解

    3.拓展延伸

    4.实际应用

    5.总结

    0.前言

    • 上一篇文章《部分经典排序算法详解(有图解)》中,
      我们通过图解的方式,详解了三种经典的排序方法

    • 本文主要讲解C语言的最后一个内容,
      也是被称为“C语言的灵魂”的内容——指针

    1.本文主要内容

    • 指针的基础知识

    • 指针的一些注意事项

    • 指针的实际应用

    2.基础知识讲解

    2.1 指针的基础概念

    • 能记录其他变量的地址的一种工具,就叫做指针

    (1)指针能解决哪些问题?
             指针能解决跨区域问题
          (即不同作用域、不同代码块之间的数据交互)

    (2)指针是如何解决这些问题的?
             指针能够通过自身指向的地址,来操作该地址所存储的值
             以此达到跨区域的数据交互问题

    2.2指针的语法定义

    2.2.1基本定义方法:
    int *p;
    

    其中,变量p即为一个整型指针变量

    Int *的意思就是该指针只能指向一个整型变量,
    该p指针变量的内存空间只能存储一个整型变量的地址

    2.2.2基本使用方法:
    int a =10;
    int *p = &a;//p指向a的地址
    printf("%d\n",*p);//输出p指向的地址的值
    

    这里从第二行开始对一些重要的细节进行解释:

    • 第二行的 “&” 表示取变量的地址,(&a表示变量a的地址)
      由于指针变量存放的是其他变量的地址,因此需要在该变量前加&

    • 第二行与第三行均有一个星号 * ,但这两行的星号* 意思并不相同
      第二行的星号表示变量p是指针
      第三行的星号表示取变量p所指向地址中存储的值(即a的值

    总结:

    • “&” 表示取变量的地址

    • 指针变量中使用星号* 表示变量p是指针
      其他情况下指针变量前加星号* 表示取变量p所指向地址中存储的值

    2.2.3指针与数组:

    指针与数组有着不少联系
    可以使用一个指针指向数组的首地址,然后通过指针来控制、访问数组:

    int *p;
    int a[20] = {};
    p = a;
    printf("%d",p[1]);//输出数组a的第二个元素
    printf("%d",p+1);//输出数组a的第二个元素
    

    我们来分析一下细节部分:

    • 因为数组a的变量名为a,该变量名所代表的就是该数组的首地址,因此可以把a赋给p,意思就是将数组a的首地址赋给指针p

    • 当p指向数组a之后,p[i]则可以用来表示a[i](效果相同)

    • 由于是int型指针变量,设数组a的首地址为0x100
      则p+1的含义是0x100 +1*4 = 0x104,实际上 p+1与p[1]同效果

    3.拓展延伸

    3.1关于指针的一些研究

    3.1.1语法相关注意事项

    看看是否能区分一下的语句的含义:

    printf("%p",score);输出的是第一个元素的地址
    printf("%p",score+1);输出的是第二个元素的地址
    printf("%d",*(score+1) );输出的是第二个元素的值
    printf("%d",*score +1 );输出的是第一个元素的值+1
    printf("%d",*score++);输出的是?
    
    注意:
    • *score++相当于( *score)++,星号优先级更高
      *(score++)则是先地址++,再与星号结合
      因此printf("%d", *score++);输出的是 *score,
      语句结束后 *score会+1

    再看看一下语句:

    char * const p  
    
    char const *p 
    
    const char *p  
    

    总结:

    • char * const p
      p是一个char型指针,const修饰的是p,p不允许改变
      该指针p是常量,不允许修改

    • char const *p 与 const char *p
      p是同一种char型指针,const修饰的是char
      指针指向的字符被看作是常量,不允许修改

     

    3.1.2其他注意事项

    (1) 指针必须要指向具体的存储空间,才能赋具体的(非地址)值
    int *p;
    *p = 10; //会报错
    

    由于p并未指向一个具体的内存空间,使用*p并对其赋值肯定会报错

    解决办法:

    ①将其他值的地址赋给p,就可以使用*p了

    ②使用malloc()与realloc()自行申请内存空间

    (2)使用malloc()与realloc()申请内存空间方法

    语法:

    int* p;
    p = (int*)malloc(10 * sizeof(int));
    p = (int*)realloc(p,20*sizeof(int));
    
    • 第二句语法可以分配10个连续的大小为4个字节的空间
      (64位中,整型空间为4个字节)

    • 第三句可以为p重新分配一个大小为20个4个字节的空间
      其中realloc中的p就是malloc的接收对象

    • 使用realloc的前提是,必须先用malloc开辟一段空间

    4.实际应用

    4.1让函数改变多个参数

    一般情况下,我们都会通过返回值来把函数中修改后的值返回出来
    由于返回值只能返回一个值
    如果需要同时修改多个参数,返回值就无法满足我们

    void add(int a,int b){
          a++;
          b++
    }
    void main(){
      int m=0,n=0;      
      add(m,n);
    }
    

    我们都知道,上面这种情况下,m与n的值最终是不会变的

    • 原因是:

    调用add()函数时,m与n将它们的值传给形参a、b,
    形参的操作并不会影响实参m、n,故最后m、n的值并不会改变

    想要解决这个问题,就需要使用指针:

    void add(int *a,int *b){
          *a++;
          *b++
    }
    void main(){
      int m=0,n=0;      
      int *p1 = &m;
      int *p2 = &n;
      add(p1,p2);
    }
    
    • 使用指针可以解决问题的原理是:

    实参传给形参的是需要操作的变量的地址,
    形参作为指针,会通过地址去操作变量
    以此来操控我们的目标变量的值

    4.2定义链表的结构

    链表相当于是通过指针来连接的

    typedef struct Node{
        int data;
        struct Node* next;
    }Node;
    

    链表中存在一个个的节点,这些节点都包括一个存放数据的数据域,
    以及存放下一个节点的地址的指针变量next

    链表的优缺点:

    • 优点:增加数据、删除数据十分方便,
      只需要改变指针的指向即可完成
    • 缺点:查找不方便,每次查找往往都伴随着大量遍历

    数组的优缺点:

    • 优点:访问某个特定位置的元素十分方便
    • 缺点:增加、删除元素极为麻烦

    5.总结

    (1)本文讲解了有关指针的基础知识、使用方法以及注意事项,希望各位读者能从中有所收获

    (2)指针是一个十分灵活的工具,关键就是:
              要理解为何要使用指针,以及指针能做些什么
    其实明白了这里两点后,就能基本知道指针该如何使用了(指概念理论方面),剩下只要多练习就可以完全把握指针了

    (3)指针看起来很难,但是只要明白其本质,并多多练习,就可以掌握,这里尤其是推荐:多编写一些与链表有关的项目 ,笔者觉得对于新手来说,练习链表的使用,是熟悉指针的最好方法之一。

    相关文章

      网友评论

          本文标题:[C语言] 想学会用指针吗?

          本文链接:https://www.haomeiwen.com/subject/rmojdctx.html