1. 数组名的理解首先给出一段代码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; }这里发现arr[0]与arr的打印结果相同我们推断arr表示arr[0]的地址这时候有人会有疑问数组名如果是数组首元素的地址那下面的代码怎么理解呢#include stdio.h int main() { int arr[10] { 1,2,3,4,5,6,7,8,9,10 }; printf(%d\n, sizeof(arr)); return 0; }输出的结果是40如果arr是数组首元素的地址那输出应该的应该是4/8才对why?其实数组名就是数组首元素(第一个元素)的地址是对的但是有两个例外1.sizeof(数组名)sizeof中单独放数组名这里的数组名表示整个数组计算的是整个数组的大小 单位是字节2.数组名这里的数组名表示整个数组取出的是整个数组的地址整个数组的地址和数组首元素 的地址是有区别的除此之外任何地方使用数组名数组名都表示首元素的地址。#includestdio.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); printf(arr %p\n, arr); return 0; }这里发现结果相同为了区分它们再举一个例子。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(arr1 %p\n, arr1); printf(arr %p\n, arr);// 取出的是数组的地址 printf(arr1 %p\n, arr1); return 0; }下面画图来理解2. 使用指针访问数组有了前面知识的支持再结合数组的特点我们就可以很方便的使用指针访问数组了。int main() { int arr[10] { 0 }; //给数组赋值为1-10 int* p arr; int sz sizeof(arr) / sizeof(arr[0]); for (int i 0; i sz; i) { *p i 1; p; } //打印 p arr;// for (int i 0; i sz; i) { printf(%d , *(p i)); //printf(%d , *(arr i)); } //arr[i] *(arri) *(pi) return 0; }3. 一维数组传参的本质数组我们学过了之前也讲了数组是可以传递给函数的这个小节我们讨论一下数组传参的本质。void test(int arr[10]) { //不能使用参数部分的数组来计算数组的元素个数 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);//arr就是首元素的地址 arr[0] return 0; }从结果来看test中的sizeof(arr)只有8个字节x64环境下这正好是地址的大小。所以本质上是这样的,在有些地方也被称为数组降级即数组降级为首元素地址void test(int* arr)完善后的代码void test(int *arr, int sz) { int i 0; for (i 0; i sz; i) { //printf(%d , *(arr i)); printf(%d , arr[i]); } }4. 冒泡排序https://visualgo.net/zh(该网站可可视化观察各种算法若有兴趣可自行研究)排序算法有很多下面通过实现冒泡排序来理解一维数组传参冒泡排序的核心思想就是两两相邻的元素进行比较。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 - 1 - i; 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; } } }即有n个数就会进行n-1趟这时只要设计一个标记变量flag便可以避免无效的循环5. 二级指针指针变量也是变量是变量就有地址那指针变量的地址存放在哪里int main() { int a 10; int* pa a; //pa就是指针变量一级指针变量 int** ppa pa;//ppa是指针变量二级指针变量 return 0; }如果想要通过二级指针访问a,需用**printf(%d\n, **ppa);//1006. 指针数组指针数组的每个元素都是用来存放地址(指针)的parr 是一个数组数组有3个元素每个元素的类型是 int* 7. 指针数组模拟二维数组下面通过模拟二维数组加深我们理解指针数组int main() { int arr1[] { 1,2,3,4 }; int arr2[] { 5,6,7,8 }; int arr3[] { 9,10,11,12 }; int* parr[3] { arr1, arr2, arr3 }; for (int i 0; i 3; i) { for (int j 0;j 4; j) { printf(%d , parr[i][j]); } printf(\n); } }parr[i] 是访问 parr 数组的元素 parr[i] 找到的数组元素指向了整型一维数组 parr[i] [j] 就是整型一维数组中的元素。 上述的代码模拟出二维数组的效果实际上并非完全是二维数组因为每一行并非是连续的。