//指针数组 // 1.是数组 // 2.是存放指针的数组 // char* arr[6]---数组元素类型+数组名+[元素个数]---存放字符指针的数组 // int * arr[5]---存放整型指针的数组 // // // 数组指针 // // // 字符指针---char*pc--指向字符的,变量中存放的是字符的地址 // 整型指针---int*pi---指向整型,变量中存放的是整形数字的地址 // // 那么数组指针就是指向数组的指针 // *p--说明这个是指针 // [元素个数]--说明前面的p是指向后面的数组的 // (*p)添加括号,不然p会与后面的[元素个数]进行组合,p就成数组名了,所以在定义数组指针的时候要将*p括起来 // (*p)[10] // int(*p)[10]--说明p是数组指针,数组内有10个元素,每个元素有的类型是int // // 那么p的类型就是int(*)[10] //int main() //{ // int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; // int(*p)[10] = &arr;//取出的是数组的地址 // //把一个数组指针的地址取出来放到数组指针变量内 // // //使用p数组指针来访问arr数组的内容 // // for (int i = 0; i < 10; i++) // { // //printf("%d", *p);//因为p里面存放的是数组的地址,那么解引用就是拿到了整个数组的地址 // //所以如果我们想访问这个数组的每个元素,我们需要做出改变 // // printf("%d", (*p)[i]);//(*p)访问了这个数组,后面加上[i],随着i的变化访问数组内的元素 // //就相当于在打印arr[i],因为p里面存的是数组的地址,*p=arr // } // return 0; //} //上面的方法略显复杂,我们进行变更 //int main() //{ // int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; // int*p= arr;//存放数组首元素的地址,直接创建指针来存放数组首元素的地址 // // for (int i = 0; i < 10; i++) // { // // printf("%d ", p[i]);//p[i]---*(p+i)--随着i的变化访问数组内的元素 // } // return 0; //} // 上面的使用数组指针访问数组有点麻烦,远不及其他的方法 //那么数组指针到底在什么地方能用上呢? // // 二维数组传参 //常规方式: //void print(int arr[3][5], int r, int c)//传过来的数组就创建一个数组来接收数组 //{ // //两层循环遍历数组,第一层解决行,第二层解决列 // for (int i = 0; i < r; i++) // { // for (int j = 0; j < c; j++) // { // printf("%d ", arr[i][j]); // } // printf("\n");//打印完一行就换行打印另一行 // } //} //int main() //{ // int arr[3][5] = { {1,2,3,4,5} ,{2,3,4,5,6} ,{3,4,5,6,7} };//创建二维数组 // print(arr,3,5);//借助函数将数组打印出来,将数组名传过去,3行5列也传过去 // // return 0; //} // //一维数组的数组名是数组首元素的地址 // 二维数组的数组名也是数组首元素的地址 // 对于上面的这个二维数组,可以理解为存放3个一维数组的数组 // 二维数组的每一行可以理解为每一行就是一维数组 // // 那么二维数组的数组名是首元素的地址,所以二维数组的地址就是第一行的地址 // // void print(int (*arr)[5], int r, int c)//传过来的数组就创建一个数组来接收数组 {//传过来的是第一行的一维数组的地址,我么用数组指针接收 //这个数组指针指向的是第一行的一维数组的5个元素 // 每个元素的返回类型就是int // 所以我们用int (*arr)[5]这个数组指针来接收 // //两层循环遍历数组,第一层解决行,第二层解决列 for (int i = 0; i < r; i++) { for (int j = 0; j < c; j++) { printf("%d ", (*(arr + i))[j]); } printf("\n");//打印完一行就换行打印另一行 } } int main() { int arr[3][5] = { {1,2,3,4,5} ,{2,3,4,5,6} ,{3,4,5,6,7} }; print(arr, 3, 5);//arr是数组首元素的地址,就是第一行的一维数组地址,不是这个一维数组首元素的地址 //这里传过去的是第一行一位数组的的地址,就是第一行一维数组的地址 //数组的地址传过去了,我们要用数组指针来接受 return 0; } //形参是传的是数组首元素的地址,那么我们就创建数组指针来接收 //对于这个数组来说 // // // 第一行1 2 3 4 5 // 第二行2 3 4 5 6 // 第三行3 4 5 6 7 // // arr指向的是第一行的,当我们想指向第二行,我们就需要arr+1, // 因为是指向数组的指针,所以+1就是直接跳过一个数组 // 那么想找到第三行的时候就直接arr+2 // // 那么在上面的循环里,打印这个二维数组我们就能这么写 // *(arr+i) // arr+i就是这个二维数组内三个一维数组的地址,那么我们对其进行解引 // 用就能访问这三个数组的内容了 // // *(arr+i)就是想当与拿到这一行 // // 那我们已经拿到了这一行,我们该如何访问每一个元素呢? // 我们 还是得通过下标访问数组内的每个元素 // // // 因为这个函数有两个循环,那么第二个循环就是我们访问这三个一维数组内的每个元素了 // 那我们就在后面添加[j]访问每个元素, // 前面的(*(arr+i))就是把访问这个二维数组内的三个一维数组 // 那么在后面加上[j]就能访问到每个元素了 // (*(arr+i))[j]------第一种写法 // // // *((*(arr+i)+j))--第二种写法 // 解释: // 因为实参传过来的是arr是二维数组的数组名,那么我们是用一个数组指针进行接收的 // ,所以arr是一个数组指针 // 这里的arr是指针啊,数组指针 // arr数组内存放的是这个二维数组里面的第一个一维数组的地址 //*(arr+i)得到的是第i行的数组的首地址,也是指向第i行第一个元素的指针 //为什么解引用得到的是地址呢? // // 因为arr+i里面存放就是第i行的地址 // 对其进行解引用得到的就是第i行的地址 // *(arr+i)得到的是第i行的地址, // 同样,arr+i里面存的是一维数组首元素的地址,对其进行解引用得到的是地址,是数组首元素的地址 // *(arr+i)得到的是一维数组首元素的地址 //那么*(arr+i)+j得到的就是这一下标为j的地址 // 对整体再次进行解引用就得到了i行j列的元素了 // //记住,这里的arr是一个数组指针
末尾涉及到(*(arr+i))[j]和 *((*(arr+i)+j))的区别
尽管二者相同但有些知识点十分复杂
关键点,这里的arr是一个数组指针,存放的是这个二维数组内的一个一维数组的地址(二维数组的首元素就是这个一维数组)
在这个函数里面arr仅仅只是一个指针