C语言数组指针-最通俗易懂

数组指针

  数组指针本质上是一种指针,用来存放数组的地址

p	 		// 是个变量
*p   		// 与*结合代表是指针变量
*p[] 		// 此时由于[]的优先级比*高 所以p现在是个数组
(*p)[]		// 所以括起来让先与*结合代表是个指针,在与[]结合代表指向数组
(*p)[10] 	// p是个指针指向一个数组,指向可以存放10个元素的数组
int (*p)[10]// p是个指针指向一个数组,指向可以存放10个元素的数组,并且指向的数组每个元素是int

int (*)[10] 是数组指针类型。


char * arr[5]的地址应该怎么被存放呢?
int main () {
	char * arr[5] = {NULL , NULL , NULL , NULL , NULL};
	char * (*ptr)[5] = &arr;
	/*
		解析:
			ptr先与*结合代表是一个指针变量,在与[5]结合代表指向一个数组,这个数组
			可以存放五个元素,并且ptr指向这个数组的每一个元素是char *
	*/
	
	return 0;
}

数组指针的使用

例1:

#include <stdio.h>
int main() {

    int arr[10] = { 1 , 2,  3 , 4 , 5 , 6 , 7 , 8,  9, 10 };
    int(*ptr)[10] = &arr;
    int i = 0;
    for (i = 0; i < 10; i++) {
    	/*
			ptr = &arr
			两边同时来个解引用:*ptr = *&arr = arr
			// 而arr又是数组名,数组名又是首元素地址
			*ptr = *&arr = arr = &arr[0]
			*ptr + i = &arr[0] + i
			*(*ptr + i) = *(&arr[0] + i)
		*/
        printf("%d " , *(*ptr + i));
    }
/*
	result: 1 2 3 4 5 6 7 8 9 10
		
*/

    return 0;
}

一维数组使用数组指针的方式绕弯路了,相对比较麻烦,用一级指针指向数组名的方式更方便。数组指针的使用场景一般在二维数组上。


例2:

#include <stdio.h>
int main() {

    int arr[3][5] = {
        {1 , 2 , 3 , 4 , 5},
        {6 , 7 , 8 , 9 , 10},
        {11 , 12 , 13 ,14 , 15}
    };
    int(*ptr)[5] = arr;
    int i = 0;
    for (i = 0; i < 3; i++) {
        int j = 0;
        for (j = 0; j < 5; j++) {
        	/*
				解析:
					ptr = arr = &arr[0]	
					// 二维数组名也代表首元素地址,而二维数组的首元素是一维数组
					// 所以首元素的地址相当于一维数组的地址给ptr类型刚好对应
					ptr + i = &arr[0] + i
					// &arr[0] 是第一行的地址 + 1相当于跳过1行 + 2相当于跳过2行
					// + i相当于跳过i行
					*(ptr + i) = *(&arr[0] + i)
					// 如果 i 是 1 的话 相当于*(&arr[0] + 1) = *&arr[1] = arr[1]   (i同理)
					// 原来是数组的地址第一个解引用相当于把&抵消了,拿到了当前这行的数组名
					// 而当前这行的数组名又相当于这行首元素的地址 arr[1] = &arr[1][0]
					*(ptr + i) + j = *(&arr[0] + i) + j
					// 当 i = 1时  *(ptr + i) = arr[1] = &arr[1][0]
					// *(ptr + i) + j = &arr[1][0] + j 代表拿到当前这行的首元素地址在 + j
					// 就是当前这行第j个元素的地址
					*(*(ptr + i) + j) = *(*(&arr[0] + i) + j)
					// 如果 i = 1 , j = 2
					// ptr = &arr[0]
					// ptr + 1 = &arr[0] + 1 = &arr[1]
					// *(ptr + 1) = *&arr[1] = arr[1] = &arr[1][0]
					// *(ptr + 1) + 2 = &arr[1][0] + 2 = &arr[1][2]
					// *(*(ptr + 1) + 2) = *&arr[1][2] = arr[1][2]
			*/
            printf("%-3d " , *(*(ptr + i) + j));
        }
        printf("\n");
    }

    return 0;
}

解析:

ptr = arr = &arr[0]	
二维数组名也代表首元素地址,而二维数组的首元素是一维数组
所以首元素的地址相当于一维数组的地址给ptr类型刚好对应
ptr + i = &arr[0] + i
&arr[0] 是第一行的地址 + 1相当于跳过1行 + 2相当于跳过2行 + i相当于跳过i行
*(ptr + i) = *(&arr[0] + i)
如果 i 是 1 的话 相当于*(&arr[0] + 1) = *&arr[1] = arr[1]   (i同理)
原来是数组的地址第一个解引用相当于把&抵消了,拿到了当前这行的数组名
而当前这行的数组名又相当于这行首元素的地址 arr[1] = &arr[1][0]
*(ptr + i) + j = *(&arr[0] + i) + j
当 i = 1时  *(ptr + i) = arr[1] = &arr[1][0]
*(ptr + i) + j = &arr[1][0] + j 代表拿到当前这行的首元素地址在 + j
就是当前这行第j个元素的地址
*(*(ptr + i) + j) = *(*(&arr[0] + i) + j)

如果 i = 1 , j = 2
ptr = &arr[0]
ptr + 1 = &arr[0] + 1 = &arr[1]
*(ptr + 1) = *&arr[1] = arr[1] = &arr[1][0]
*(ptr + 1) + 2 = &arr[1][0] + 2 = &arr[1][2]
*(*(ptr + 1) + 2) = *&arr[1][2] = arr[1][2]
  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值