指针某些内容的理解,指针和数组的关系

理解指针的某些元素的概念


  比如:int *p,a=3;
         p=&a;

    1.这里的p是指针变量,用来存放地址的变量,32地址线时内存大小为4个字节,64地址线内存大小为8个字节;
    2.& 是取地址运算符,p=&a就相当于将p=a的地址的值(p存放的是地址)
    3.*p就是取a地址的值(定义指针变量--> 类型名 *指针变量名称)  比如(int *p)
    4.指针类型和指针所指向的类型
        int *p的指针类型为int * (p是指针变量)
        int *p的指针所指向的类型是int型,

    5.地址是一种编号,是连续性的,是一种数据


指针变量的引用


    1.使用变量性: printf("%d",a);
    2.指针访问  : printf("%d",*p);(这里的*号是取值运算符,单目运算符,在定义指针是的*号只是单纯的声明这个是一个指针)

指针变量的运算:(+ - ++ --)4种运算,(根本上就是指针的偏移)
    指针变量上存放的是一个地址,存放的地址之间又是连续的
    比如:第一个地址为1000,那么下面地址为1001,1002,1003....
    所以说这里你通过加一就可以指向下一个地址了(所以不存在其他的运算符)
    
指针变量的加减,以指针所指向的类型空间单位进行偏移
    比如:char*p char类型 1个字节 p+1(指针变量的运算,这里表示指向下一个内存空间)  --->地址增加1个字节
        int*p char类型 4个字节 p+1(指针变量的运算,这里表示指向下一个内存空间)  --->地址增加4个字节
        double*p char类型 8个字节 p+1(指针变量的运算,这里表示指向下一个内存空间)  --->地址增加8个字节

 

注:首地址:一段内存空间中第一个存储单位的地址.
     指针变量的加减,以指针所指向的类型空间为单位进行偏移(理解好这两句话才可以更加容易理解指针和数组的关系)

一维数组和指针


比如说我定义一个数组 int a[5]={0,1,2,3,4}   这个数组名a就是这个数组的 首地址
1.a的类型是int * 指向数组的第一个元素,这里指向a[0]
2.a[0]的类型是int型

注意:这里数组的&a与a的区别
    &a这个地址指向的是整个数组,&a的类型为  int(*)[5]  ,

           &a+1-->加了20(4*5)个字节,意思是一整个数组为一个单元进行偏移.
    a(数组的名称)的类型为   int *    a+1--->加4个字节//代码解释

 

 

2.访问数组元素
    1.下标法
            比如:a[1]....


    2.指针法
            比如:
                    for(int i=0;i<5;i++){
                        printf("%d\n",*(p+i));//p的地址是不会变的
                    }
                    这里的*(p+i)的意思是取p+1,p+2,p+3...的地址的值


                    也能写成
                     for(int i=0;i<5;i++){
                        printf("%d\n",*p++);//p的地址发生变化(区别)
                    }//这里的*p++,就是也是和上面*(p+i)一样的

 


问题:
    1.为什么这里的p++不需要用括号括起来,这是因为++是双目运算符和*(单目运算符)的优先级一样,但遵守从右往左运算,先运算++后调用*;
    2.*的优先级又比+的优先级高所以得加个括号,使其先运算里面再调用

注意:总所周知,定义数组 int a[5]={0,1,2,3,4},
    除了可以用定义指针*p指向数组的第一个元素之外,
    还有用数组名a指向a[0](数组的第一个元素)
(上面说过数组名a的类型是 int* ,指向数组的第一个元素.)

注意在这种情况下, 我们用指针法时只能用*(a+i),不能用*a++;
原因很简单:a时数组名,也是首地址,上面说过*a++会改变a的地址值,这就相当于把整个数组都改了
所以:数组名不能够随意改变,不能改变,会报错.


二维数组和指针


    int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};//3行4列
    所有的多维数组都可以分解为多个一维数组
    数组名:a
    a是指向a[0]这个一维数组,a的类型为 int(*)[4]也就是上面{1,2,3,4}以这个为一个单元的内存地址,所以a+1-->是增加16个字节
    a[0]是一个一维数组{1,2,3,4}的数组名
    a[0]是指向a[0][0]这个int元素的地址,a[0]的类型为int *,所以a[0]+1-->增加4个字节

4.推广
    int a[2][3][4]

    &a指向是整个三维数组,类型是 int(*)[2][3][4]
    a指向的是一个二维数组,类型是int (*)[3][4]
    a[0]指向的是一个一维数组,类型是int (*)[4]
    a[0][0]指向的是一个元素,类型是 int *

   引用m行n列的元素
    a[m][n]//下标法
    *(a[m]+n)//用下标法具体到某个数组后进行偏移
    *(*(a+m)+n)//这里的*(a+m)最外层a[0]进行偏移到a[m],然后再进行偏移到n
    

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我不吃牛肉!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值