• C语言指针学习


      C语言学过好久了,对于其中的指针却没有非常明确的认识,趁着有机会来好好学习一下,总结一下学过的知识,知识来自C语言指针详解一文

    一:指针的概念

      指针是一个特殊的变量,里面存储的数值是内存里的一个地址。学好指针,重要的是搞清楚指针的四个方面的内容:指针的类型、指针所指向的类型、指针所指向的内存区、指针本身占据的内存区。

    1、 如何判断指针的类型呢:

      

    int *p;
    char *p;
    int **p;
    int (*p)[3];
    int *(*p)[4];
    

      上面的五个声明,指针的类型分别是:int *、char *、int ** 、 int (*)[3]、int *(*)[4];是不是非常简单,就是把变量名去掉,剩下的就是指针的类型。

    2、指针所指向的类型

    int *p;
    char *p;
    int **p;
    int (*p)[3];
    int *(*p)[4];
    

      上面五个声明,指针所指向的类型分别是:intchar int *int()[3]int *()[4],找出规律了吗?就是把变量名和一个*去掉,剩下的就是指针所指向的类型。特别强调:指针的类型和指针所指向的类型是不同的概念。

    3、指针所指向的内存区或者指针的值

      指针的值是指针本身所存储的数值,这个值被编译器当作一个地址,而不是而不是一个一般的数值。在32位程序里,所有的类型的指针的值都是一个32位数,因为32位程序中内存地址全部都是32位字长。

      指针所指向的内存区就是从指针的值所代表的内存区开始,长度为sizeof(指针所指向的类型)的一篇内存区。以后,我们说一个指针的值是XX,就代表了该指针指向了以XX为首地址的一片内存区域;我们说一个指针指向了某个内存区域,相当于指针的值就是该内存区域的首地址。

      指针指向谁,就把谁的地址赋给指针。

    4、指针本身所占据的内存区

      指针本身占据了多大的内存。用sizeof(指针的类型)测试一个就知道了。在32位平台里,指针本身占据了四个字节的长度。

    二、指针的算术运算

      

    char a[20];
    int *p=a;
    p++;
    

      指针p的类型是 int * ,指针所指向的类型是int ,它被初始化位指向整形变量a,接下来指针p被加了1,编译器是这样处理的:它把指针p的值加上了sizeof(int),在32位程序里,是加上了4.由于地址是用字节做单位的,故p的地址由原来的a的地址指向了加四个字节后的高地址。

      由于char类型的长度是一个字节,所以原来p是指向数组从0开始的四个字节,现在指向了从第四个字节开始的四个字节

      我们可以用一个指针和一个循环来遍历一个数组:

      

    int arr[20];
    int *p=arr;
    .......//此处略去整数型赋值的代码
    for(i = 0; i<20 ; i++)
    {
        (*p)++;
        P++;        
    }
    

      这个例子将整数型数组各个单元的值加1,由于每次循环都将指针p,所以每次循环都能访问数组的下一个单元。

    char a[20];
    int *p=a;
    ...
    ...
    p+=5;
    

      在这个例子中,p被加上了5,从编译器的角度看:将指针p的值加上sizeof(int),在32位恒旭中就是加上了5*4=20.由于地址的单位十字街,故现在p指向刚开始高字节方向的20个字节。在这个例子中,没加5之前的p指向数组第0个单元开始的四个字节,加5后,p已经指向数组的合法范围之外了。虽然这种情况在应用上会出现问题,但在语法上是可以。这体现了指针的灵活性。

      总结一下:一个指针,加上一个整数n后,结果是一个新的指针pnew,pnew的类型和pnew所指向的类型与pold的类型都是一样的。pnew的值比起pold的值增加了n*sizeof(p指向的类型)个字节。加是往高字节移动,减是往低字节移动。

    三 运算符&和*

      &是取地址运算符,*在书上叫做间接运算符。&a的运算结果是一个指针,指针的类型是a的类型加一个*。指针所指向的类型是a的类型,指针所指向的地址就是a的地址。*p的结果是p所指向的结果,类型是p的类型,占用的地址就是p所指向的地址

    int a =12;
    int b;
    int *p;
    int *ptr;
    
    p=&a//&a的结果是一个指针,指针的类型是一个int *,指针所指向的数据类型是int ,指向的地址是a的地址。
    
    *p=24;//*p的结果,它的类型是int,它所占用的地址是p所指向的地址,显然*p就是变量a
    
    *ptr=&P;//p本身就是一个指针了,对p在取地址,那么 该指针的类型是int **,指针所知下个的类型是 int * 。指针所指向的地址就是p的地址
    
    **ptr=34;// *ptr的结果就是ptr所指向的东西。在这里是一个指针,对这个指针在做一次*运算,。结果就是一个int 类型的变量
    

    四 指针表达式

      一个表达式的最后结果如果是一个指针,这个表达式就叫做指针表达式

      

    int a ,b ;
    int array[10];
    int *pa;
    
    pa=&a;//指针表达式
    int **ptr = &pa;//表达式
    *ptr=&b;//表达式
    pa=array;
    pa++;//表达式
    
    
    char arr[20];
    char **parr =arr//如果把arr看作指针的话,arr也是指针表达式
    char *str;
    
    str=*parr;//指针表达式
    str=*(parr+1);//指针表达式
    

      由于指针表达式的结果是一个指针,所以指针表达式也需要具有指针的四个要素:指针的类型,指针所指向的类型、指针指向的内存区、指针自身占据的内存区。

      指针在左边表示赋值,指针在右边表示取值。

    未完待续

  • 相关阅读:
    LeetCode 222.完全二叉树的节点个数(C++)
    LeetCode 704.二分查找(C++)
    LeetCode 441.排列硬币(C++)
    LeetCode 981.基于时间的键值存储(C++)
    LeetCode 167.两数之和(C++)
    LeetCode 367.有效的完全平方数(C++)
    LeetCode 881.救生艇(C++)
    LeetCode 860.柠檬水找零(C++)
    LeetCode 870.优势洗牌(C++)
    bootstrap
  • 原文地址:https://www.cnblogs.com/kui0621/p/4056389.html
Copyright © 2020-2023  润新知