C语言:指针从基础到进阶
数组名的理解
还记得上一篇博客出现了这么一段关于用指针访问数组的代码。
1 2
| int arr[10] = {1,2,3,4,5,6,7,8,9,10}; int *p = &arr[0];
|
这里用&arr[0]拿到了数组首元素的地址,但其实数组名在大部分情况下本来就是首元素的地址
1 2 3 4 5 6 7 8
| #include <stdio.h> 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; }
|
关于详细情况可以在我的另一篇博客了解:C语言中关于数组名什么情况为首元素地址,什么情况为整个数组的地址的问题
使用指针访问数组
有了前面的基础,我们就可以很方便的用指针访问数组了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #include <stdio.h> int main() { int arr[10] = {0}; i = 0; int sz = sizeof(arr)/sizeof(arr[0]); int* p = arr; for(i=0; i<sz; i++) { scanf("%d", p+i); } for(i=0; i<sz; i++) { printf("%d ", *(p+i)); } return 0; }
|
在上面的代码的中将p+i换成p[i]也能正常打印本质上p[i]和*(p+i)是一样的,同理arr[i]等价于*(arr+i)。
一维数组传参的本质
这里直接给答案:数组名是数组⾸元素的地址;那么在数组传参的时候,传递的是数组名,也就是说一维数组传参的本质就是传递数组首元素的地址。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| include <stdio.h> void test1(int arr[]) { int sz1 = sizeof(arr)/sizeof(arr[0]); printf("sz1 = %d\n", sz1); } void test2(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 sz = sizeof(arr)/sizeof(arr[0]); printf("sz = %d\n", sz); test1(arr); test2(arr); return 0; }
|
输出结果:

冒泡排序
后面我会出一期专门的排序算法,手撕常见排序算法!这里主要说关于指针的知识。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| void bubble_sort(int arr[], int sz) { int i = 0; for(i=0; i<sz-1; i++) { int j = 0; for(j=0; j<sz-i-1; j++) { if(arr[j] > arr[j+1]) { int tmp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = tmp; } } } } int main() { int arr[] = {3,1,7,5,8,9,0,2,4,6}; int sz = sizeof(arr)/sizeof(arr[0]); bubble_sort(arr, sz); for(i=0; i<sz; i++) { printf("%d ", arr[i]); } return 0; }
void bubble_sort(int arr[], int sz) { int i = 0; for(i=0; i<sz-1; i++) { int flag = 1; int j = 0; for(j=0; j<sz-i-1; j++) { if(arr[j] > arr[j+1]) { flag = 0; int tmp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = tmp; } } if(flag == 1) break; } } int main() { int arr[] = {3,1,7,5,8,9,0,2,4,6}; int sz = sizeof(arr)/sizeof(arr[0]); bubble_sort(arr, sz); for(i=0; i<sz; i++) { printf("%d ", arr[i]); } return 0; }
|
二级指针
指针变量也是变量啊,那么指针变量也会有地址,指针变量的地址就储存在二级指针变量里面,二级指针变量也有地址,就存在三级指针变量里面……
1 2 3 4 5
| int a = 10; int* pa = &a; printf("%d\n",*pa); int** ppa = &pa; printf("%d\n",**ppa);
|
指针数组
指针数组是指针还是数组???
其实指针数组还是数组,只不过这个数组里面放的都是指针。里面的每个元素都是int*类型的。

我们可以类⽐⼀下,整型数组,是存放整型的数组,字符数组就是存放字符的数组。

指针数组模拟二维数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| int main() { int arr1[] = {1,2,3,4,5}; int arr2[] = {2,3,4,5,6}; int arr3[] = {3,4,5,6,7}; int* parr[3] = {arr1, arr2, arr3}; int i = 0; int j = 0; for(i=0; i<3; i++) { for(j=0; j<5; j++) { printf("%d ", parr[i][j]); } printf("\n"); } return 0; }
|

parr[i]是访问parr数组的元素,parr[i]找到的数组元素指向了整型⼀维数组,parr[i][j]就是整型⼀维数组中的元素。
上述的代码模拟出⼆维数组的效果,实际上并⾮完全是⼆维数组,因为每⼀⾏并⾮是连续的。
本期博客到这里就结束了,如果有什么错误,欢迎指出,如果对你有帮助,请点个赞,谢谢!