文章目录
- 引入
- 数组名的理解
- 使用指针访问数组
- 一维数组传参的本质
- 二级指针
- 指针数组
- 指针数组模拟二维数组
引入
指针和数组到底是啥关系,咋老看见他俩在一起使用,这篇文章我们就来看一下数组和指针之间的关系
数组名的理解
我们直接来看下面这个代码,你觉得预期的输出结果是什么呢?
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };printf("&arr[0] = %p\n", &arr[0]);printf("arr = %p\n", arr);return 0;
}
输出结果是,两行一摸一样
我们发现数组名和数组⾸元素的地址打印出的结果⼀模⼀样,数组名就是数组⾸元素(第⼀个元素)的地
址。
数组名 = 数组首元素的地址 这句话不完全对,在以下两种特殊情况下就不再成立
sizeof(数组名)
,sizeof中单独放数组名,这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩,单位是字节&数组名
,这⾥的数组名表⽰整个数组,取出的是整个数组的地址(整个数组的地址和数组⾸元素的地址是有区别的)
除了这两种特殊情况,数组名就等价于数组元素的首地址
我们再看下面代码
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };printf("&arr[0] = % p\n", &arr[0]);printf("arr = % p\n", arr);printf("&arr = % p\n", &arr);return 0;
}
运行结果又是三行一样的数据
哎?奇怪了,你不是说&arr(数组名)
表示整个数组,并且取出的是整个数组的地址吗?这里为啥结果又一样了?
看官你先别急,你再看下面的代码
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };printf("&arr[0] = %p\n", &arr[0]);printf("&arr[0]+1 = %p\n", &arr[0] + 1);printf("arr = % p\n", arr);printf("arr + 1 = % p\n", arr + 1);printf("&arr = % p\n", &arr);printf("&arr + 1 = % p\n", &arr + 1);return 0;}
这⾥我们发现&arr[0]和&arr[0]+1相差4个字节,arr和arr+1相差4个字节,是因为&arr[0]和arr都是⾸元素的地址,+1就是跳过⼀个元素。
但是&arr和&arr+1相差40个字节,这就是因为&arr是数组的地址,+1操作是跳过整个数组的。
看完之后悟了,原来上面说的没有问题,只是在打印数据的时候,用数组首元素的地址来表示数组的地址
使用指针访问数组
int main()
{int arr[10] = { 0 };int i = 0;int sz = sizeof(arr) / sizeof(arr[0]);//输⼊int* p = arr;for (i = 0; i < sz; i++){scanf("%d", p + i);//scanf("%d", arr+i);//也可以这样写}//输出for (i = 0; i < sz; i++){printf("%d ", *(p + i));//printf("%d ", p[i]);//也可以这么写}return 0;
}
实际上,在上面的代码中,p
和arr
是完全等价的
p[i]
就等价于*(p + i)
,甚至你想的话这么写也没问题i[p]
,就是说[]
只是一个操作符,这个操作符的中文意思就是,元素地址加减偏移量,再解引用访问
一维数组传参的本质
我们想一下下面这个代码结果是什么
void test(int arr[])
{int sz2 = sizeof(arr) / sizeof(arr[0]);printf("sz2 = %d\n", sz2);
}
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int sz1 = sizeof(arr) / sizeof(arr[0]);printf("sz1 = %d\n", sz1);test(arr);return 0;
}
传一维数组给函数,函数的形式参数用一个一维数组来接收,这个思路非常顺呀,按理来讲,输出的两个结果应该是一样的,但是运行结果却不是这样
sz2
算出来是1,说明sizeof(arr)
等于4,说明传参有问题,我们再看函数的参数,arr
数组名,数组名是数组首元素的地址,所以在这里,根本没有传一个数组过去,而是传了一个一级指针
总结:一维数组传参的本质是传了数组首元素的地址
二级指针
存放变量地址的叫做指针变量,那存放指针变量地址的变量叫什么呢?
那就是二级指针,二级指针存放指针变量的地址,像这样
int main()
{int a = 10;int *pa = &a;int **ppa = &pa;return 0;
}
不过这里要提醒各位的是,二级指针和二维数组没有啥特殊的关系
指针数组
第一件事儿我们先弄清楚,指针数组是指针还是数组,我们类比整形数组,字符数组,就容易想到,指针数组,就是存放指针变量的数组,数组中的元素又指向一块儿空间
指针数组模拟二维数组
int main()
{int arr1[5] = { 1,2,3,4,5 };int arr2[5] = { 2,3,4,5,6 };int arr3[5] = { 3,4,5,6,7 };int* arr[3] = { arr1, arr2, arr3 };for (int i = 0; i < 3; i++){for (int j = 0; j < 5; j++){printf("%d ", arr[i][j]);//arr[i][j]<==>*(*(arr+i)+j)}printf("\n");}return 0;
}
完