C语言----关于二维数组传参的本质相关的知识点(数组指针、指针数组)

简介: C语言----关于二维数组传参的本质相关的知识点(数组指针、指针数组)
//指针数组
// 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仅仅只是一个指针

目录
相关文章
|
存储 人工智能 Java
一文彻底搞定C语言中的二维数组
本文详细介绍了C语言中的多维数组,包括二维和三维数组的定义、初始化方式、内存布局及遍历方法。通过具体示例讲解了多种赋值技巧,并强调了数组在内存中按行存放的特点。希望这些内容能帮助你在编程路上不断成长!君志所向,一往无前!
1668 1
一文彻底搞定C语言中的二维数组
|
存储 NoSQL 编译器
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
指针是一个变量,它存储另一个变量的内存地址。换句话说,指针“指向”存储在内存中的某个数据。
640 7
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
|
存储 编译器 C语言
【C语言】指针大小知多少 ?一场探寻C语言深处的冒险 !
在C语言中,指针的大小(即指针变量占用的内存大小)是由计算机的体系结构(例如32位还是64位)和编译器决定的。
1933 9
|
安全 程序员 C语言
【C语言】指针的爱恨纠葛:常量指针vs指向常量的指针
在C语言中,“常量指针”和“指向常量的指针”是两个重要的指针概念。它们在控制指针的行为和数据的可修改性方面发挥着关键作用。理解这两个概念有助于编写更安全、有效的代码。本文将深入探讨这两个概念,包括定义、语法、实际应用、复杂示例、最佳实践以及常见问题。
680 7
|
存储 人工智能 Java
一文轻松拿捏C语言的指针的基础使用
本文介绍了C语言中的指针概念,包括直接访问和间接访问内存的方式、指针变量的定义与使用、取址运算符`&`和取值运算符`*`的应用,帮助读者深入理解指针这一C语言的核心概念。君志所向,一往无前!
474 0
|
存储 算法 程序员
C 语言指针详解 —— 内存操控的魔法棒
《C 语言指针详解》深入浅出地讲解了指针的概念、使用方法及其在内存操作中的重要作用,被誉为程序员手中的“内存操控魔法棒”。本书适合C语言初学者及希望深化理解指针机制的开发者阅读。
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
算法 C语言
C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项
本文深入讲解了C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项,通过实例演示了文件操作的基本流程,帮助读者掌握这一重要技能,提升程序开发能力。
1047 3
|
容器
在使用指针数组进行动态内存分配时,如何避免内存泄漏
在使用指针数组进行动态内存分配时,避免内存泄漏的关键在于确保每个分配的内存块都能被正确释放。具体做法包括:1. 分配后立即检查是否成功;2. 使用完成后及时释放内存;3. 避免重复释放同一内存地址;4. 尽量使用智能指针或容器类管理内存。
|
程序员 C语言
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门。本文深入探讨了指针的基本概念、声明方式、动态内存分配、函数参数传递、指针运算及与数组和函数的关系,强调了正确使用指针的重要性,并鼓励读者通过实践掌握这一关键技能。
406 1