-
一维数组的空间排布如下:
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 */
-
通过指针访问二维数组
p p[0]+1 p[1] *(p+1)+1 p+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和指针》