指针和数组小结

  • 一维数组的空间排布如下:

    arr
    arr[0]arr[1]arr[2]arr[3]
  • 二维数组的空间排布如下:

    arr
    arr[0]arr[1]arr[2]
    arr[0] [0]arr[0] [1]arr[0] [2]arr[1] [0]arr[1] [1]arr[1] [2]arr[2] [0]arr[2] [1]arr[2] [2]
  • 指针的移动:指针每次移动的尺度为其所指向数据类型的大小

  • 指针移动例子

    	int arr[10];
    	void *p = arr;
        printf("%x\t", p);
        p = (int*)p + 1;		//此时p指向类型为int,每次移动sizeof(int)
        printf("%x\t", p);
        p = (long long*)p + 1;	//此时p指向类型为long long,每次移动sizeof(long long)
        printf("%x\t", p);
        p = (char*)p + 1;		//此时p指向类型为char,每次移动sizeof(char)
        printf("%x\t", p);
    	/* 假设arr地址为60fec0,int为4字节大小,long long为8字节大小,输出为: 
    		60fec0    60fec4    60fecc    60fece	*/
    
  • 通过指针访问二维数组

    pp[0]+1p[1]*(p+1)+1p+2*p+8
    arr
    arr[0]arr[1]arr[2]
    arr[0] [0]arr[0] [1]arr[0] [2]arr[1] [0]arr[1] [1]arr[1] [2]arr[2] [0]arr[2] [1]arr[2] [2]
    	int arr2[3][4];			//由3个4元素的一维数组组成,3行4列
        int (*p2)[4] = arr2;	//p2为数组指针,指向类型为:4元素的一维数组
    	int *pp      = arr2;	//pp为int类型指针
    
        for (i = 0; i < 3; i ++)
            for (j = 0; j < 4; j ++)
                printf("%x  ", &arr2[i][j]);
        printf("\n");
    	for (i = 0; i < 3; i ++)
            for (j = 0; j < 4; j ++)
                printf("%x  ", pp ++);	//因为pp指向int类型,所以每次移动距离为int大小
        printf("\n");
    
    	/*p2[m][n]为直接下标访问;
    	  p2[m]表示指针移动m次,范围为4元素一维数组的大小,同时解引用该地址,所以此时为p2[m]的意思为arr2[m][0]地址,
    	  所以p2[m]+2表示指针移动2次,但范围为单个int元素大小*/
        printf("%x  %x  %x  %x  ", &p2[0][0], &p2[0][1], p2[0]+2, p2[0]+3);
    	/* p2+1表示指针移动1次,范围为4元素一维数组的大小
           *(p2+1)即为解引用操作,此时为arr2[1][0]地址
           (*(p2+1))[1]表示直接下标访问
           *(p2+1)+2表示指针移动2次,但范围为单个int元素大小
           *p2表示解引用p2,此时为arr2[0][0]地址,*p2+7即为移动7次,但范围为单个int元素大小,指向arr[1][4]*/
        printf("%x  %x  %x  %x  ", &(*(p2+1))[0], &(*(p2+1))[1], *(p2+1)+2, *p2+7);
        p2 ++; p2 ++;		//指针移动2次,每次范围为4元素一维数组的大小
    	/* p2即为arr[2]地址,*p2表示解引用,此时指向arr[2][0]
        	所以*p2+m为移动m次, 但每次范围为单个int元素大小*/
        printf("%x  %x  %x  %x  ", p2, *p2+1, *p2+2, *p2+3);
    
    	/* 假设arr地址为60fe90,int为4字节大小,输出为:
    		60fe90  60fe94  60fe98  60fe9c  60fea0  60fea4  60fea8  60feac  60feb0  60feb4  60feb8  60febc
    		60fe90  60fe94  60fe98  60fe9c  60fea0  60fea4  60fea8  60feac  60feb0  60feb4  60feb8  60febc
            60fe90  60fe94  60fe98  60fe9c  60fea0  60fea4  60fea8  60feac  60feb0  60feb4  60feb8  60febc	*/
    
  • 二维指针:指向指针的指针
    在这里插入图片描述

     int **p;		//二维指针,指向指针的指针
    /* 申请一个int类型指针数组,元素数量为4,返回指针数组首地址给p */
      p = (int**)malloc(sizeof(int*)*4);
    
    /*各个指针数组元素的地址*/
      printf("%x  %x  %x  %x\r\n", &p[0], &p[1], &p[2], &p[3]);
    /*各个指针数组元素未赋值,因此输出为任意值*/
      printf("p[0]:%x  p[1]:%x  p[2]:%x  p[3]:%x\r\n\n",p[0], p[1], p[2], p[3]);
    
      int arr[6];
      p[0] = arr;							//数组arr首地址赋值给p[0]
      p[1] = (int*)malloc(sizeof(int)*7); //申请元素个数为7的int类型数组,返回数组首地址给p[1]
      p[2] = (int*)malloc(sizeof(int)*8); //申请元素个数为8的int类型数组,返回数组首地址给p[2]
      p[3] = (int*)malloc(sizeof(int)*9); //申请元素个数为9的int类型数组,返回数组首地址给p[3]
    
    /*输出申请的数组首地址*/
      printf("p[0]:%x  p[1]:%x  p[2]:%x  p[3]:%x\r\n\n",p[0], p[1], p[2], p[3]);
    
    /* 因为p为指向int指针的指针,所以p+1移动的范围为int指针的大小* */
      printf("%x  %x  %x  %x\n\n", *p, *(p+1), *(p+2), *(p+3));
    
    /* 下标访问,得到各元素地址值 */
      printf("%x  %x  %x  %x  %x  %x\r\n",\
                      &p[0][0],&p[0][1],&p[0][2],&p[0][3],&p[0][4],&p[0][5]);
      printf("%x  %x  %x  %x  %x  %x  %x\r\n",\
                  &p[1][0],&p[1][1],&p[1][2],&p[1][3],&p[1][4],&p[1][5],&p[1][6]);
      printf("%x  %x  %x  %x  %x  %x  %x  %x\r\n",\
                  &p[2][0],&p[2][1],&p[2][2],&p[2][3],&p[2][4],&p[2][5],&p[2][6],&p[2][7]);
      printf("%x  %x  %x  %x  %x  %x  %x  %x  %x\r\n\n",\
                  &p[3][0],&p[3][1],&p[3][2],&p[3][3],&p[3][4],&p[3][5],&p[3][6],&p[3][7],&p[3][8]);
    
    /* 输出为:
    b915e0  b915e4  b915e8  b915ec
    p[0]:b93480  p[1]:b915c0  p[2]:746c7561  p[3]:7070415c
    
    p[0]:60fed0  p[1]:b915f8  p[2]:b91620  p[3]:b91648
    
    60fed0  b915f8  b91620  b91648
    
    60fed0  60fed4  60fed8  60fedc  60fee0  60fee4
    b915f8  b915fc  b91600  b91604  b91608  b9160c  b91610
    b91620  b91624  b91628  b9162c  b91630  b91634  b91638  b9163c
    b91648  b9164c  b91650  b91654  b91658  b9165c  b91660  b91664  b91668	*/
    
  • 其他

    	int a[100][30];
        int (*b)[30];
        b = a;
    	/* b[19]表示为a[19]地址,b[8]表示为a[8]地址,原本为指向 元素为30的一维数组 的指针
           后转换为指向 int类型的指针
           因此c的值为(28-8)*30 = 600 */
        int c = (int)( (int*)b[28] - (int*)b[8] );
    
参考
  • 《C Primer Plus》
  • 《C和指针》

简单总结,不当之处请在评论区指出

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值