【C语言进阶】⑤关于数组传参和指针传参辨析
文章目录
- 一、数组
- 1.1.一维数组
- 1.2.二维数组
- 1.3.指针和数组
- 二、数组传参
- 2.1一维数组传参
- 2.2二维数组传参
- 2.3小结
- 三、指针传参
- 3.1一维指针传参
- 3.3二级指针传参
- 四、感谢与预告
一、数组
1.1.一维数组
int arr1[]={1,2,3,4,5,6,7,8};
- 数组名 arr1 一般表示的是首元素的地址,以下两种情况除外:
(1)&arr1表示整个数组元素的地址;
(2)sizeof(arr),其中arr表示的是整个数组,sizeof(arr)计算的是整个数组的大小,单位是字节;- arr和&arr的辨析,请下面图解:
1.2.二维数组
int arr2[3][5] = {{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7,}};
- 而此时arr2也表示数组首元素的地址,但对于二维数组而言,它的首元素地址就是他第一行的地址;
- 请看下面图解:
1.3.指针和数组
请看下面事例:
●int arr[5];
●int *parr1[10];
●int (*parr2)[10];
●int (*parr3[10])[5];
想一想,它们各自表示什么含义呢?
答:
- arr是整型数组
- parr1是整型指针数组,里面存储了10个指针
- parr2是数组指针,一个指向大小为10的数组的指针
- parr3是一个存储int(*)[5],即存储数组指针的数组。
例如:我们知道int arr[3];表示一个int类型含有3个元素的数组,而对于parr3[10]则也表示一个数组,去掉parr3[10]后,这个int(*)[5],我们知道是表示一个指向含有五个元素的数组的指针;所以int(*parr3[10])[5],则表示parr3是一个储存数组指针的数组,该数组能储存10个数组指针,而每个数组指针又指向一个含有5个元素的数组,每个元素是int类型。
请看图解:
二、数组传参
2.1一维数组传参
请看事例1:
①void test(int arr[]){}
②void test(int arr[10]){}
③void test(int *arr){}
④void test2(int *arr[20]){}
⑤void test2(int **arr){}
int main()
{int arr[10] = {0};int *arr2[20] = {0};test(arr);test(arr2);}
分析1: 对于test(arr):
(1)①void test(int arr[]){}
:
arr是一个int类型数组,数组名arr表示数组首元素地址,此时实参传到①时,可行;因为,我们知道此时传递过去的是数组arr的首地址,而①中的形参也是一个数组,虽说这个形参数组没有设置大小,但是我们知道,本质上来说,形参只是接收传过来的地址,并不会真的会在内存中开辟一个内存空间去存放传过来的实参;所以,传一个数组首元素地址,我们拿一个数组来接收,没问题!
(2②void test(int arr[10]){}
:
实参arr传递到②,可行,但是实际上此时的形参int arr[10],并不会在内存中开辟一个大小为10的内存空间,此时的10是没有意义的,可写可不写。
(3)③void test(int *arr){}
:
实参arr传递到③时,可行;我们知道此时的实参arr表示一个整型的地址,而对于③void test(int *arr)来说,拿一个int类型的指针作为形参来接收实参arr(整型地址),指针变量就是储存地址的,而此时int类型地址用int类型指针来储存,完全没有问题!
分析2.:对于 test(arr2):
(1)int *arr2[20] = {0};
arr2是一个指针数组,存储了20个指针;此时数组名arr2表示的是第一行首元素的地址,而我们知道,arr2储存的都是int类型的指针(int*),所有总的来说,arr2表示的是首元素int类型的指针的地址;
(2)④void test2(int *arr[20]){}
:
此时arr2作为实参传递到④,而void test2(int *arr[20]),用一个指针数组来接收,没问题,而且我们知道形参里面20是没有意义的,可以不写。
(3)⑤void test2(int **arr){}
:
当arr2作为实参传递到⑤时,对于void test2(int **arr),我们知道此时int *arr表示一个二级指针,一个指向int类型指针(int)地址的二级指针,而实参传过去的也是一个int类型的指针的地址,用二级指针来接收,完全没问题,而且只能用二级指针来接收,其他的都不行!
2.2二维数组传参
请看事例2:
①void test(int arr[3][5]){}
②void test(int arr[][]){}
③void test (int arr[][5]){}
④void test(int *arr){}
⑤void test (int* arr[5]){}
⑥void test(int (*arr)[5]){}
⑦void test(int **arr){}
int main()
{int arr3[3][5] = {0};test(arr);
}
分析: test(arr);
(1)①void test(int arr[3][5]){}
:
实参arr3传到①,可行;二维数组传给二维数组,完全没问题;
(2)②void test(int arr[][]){}
:
实参arr3传到②,不可行;因为我们知道,对于二维数组int arr[3][5]而言,只能省略第一个[],所有程序运行时,编译器会报错!
(3)③void test (int arr[][5]){}
:
实参传到③,可行;
(4)④void test(int *arr){}
:
不可行;我们知道二维数组传参时,arr3表示的是首元素的地址,二维数组的首元素地址是第一行(一维数组)的地址;所以实参为arr3二维数组的首元素一维数组地址,但是用形参一级指针int* arr来接收一个含有五个元素的数组的地址是不可行的;必须用一个含有五个元素的数组指针来接收;
(5)⑤void test (int* arr[5]){}
:
此时void test(int* arr[5]),形参部分表示的是一个指针数组(存储的是int类型指针),用一个指针数组(是数组,不能接收地址),来接收一个二维数组的地址是不可行的;
(6)⑥void test(int (*arr)[5]){}
:
此时void test(int (*arr)[5])是一个数组指针,表示的是一个指向含有五个元素的数组的指针,用它来接收二维数组首元素的地址,因为我们知道,这个二维数组的首元素也是一个含有五个元素一维数组,所有完全没有问题!
(7)⑦void test(int **arr){}
:
void test(int **arr)表示的是一个二级指针;用二级指针来接收二维数组的首元素地址是不可行的,因为实参二维数组传过去的不是一个二级指针,而是一个含有五个数组指针;
}
2.3小结
- 对于一维数组int arr={1,2,3}来说,数组名arr 表示首元素的地址,除了下面两种情况:
(1)sizeof(arr),此时的arr表示的是整个数组,计算的是整个数组的大小,单位是字节
(2)&arr表示的是整个数组的地址,它和arr是不相同的,&arr是一个整体的数组的首地址,而arr只是数组元素中的第一个元素的地址,他们的数值相同,但加减整数时,所跨越的范围是不同的,这里可以参考上一篇文章,指针类型的解引用加减范围!- 对于二维数组int arr2[3][5]={{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7}},来说,数组名arr2表示的是首元素的地址,而二维数组的首元素是一个一维数组,所以二维数组的首元素地址就是其第一行的首地址!
- 对于二维数组而言,int arr3[][5]={0};
第一个[]里面的数值可以省略不写,但第二个[]里的数值必须写!
三、指针传参
3.1一维指针传参
请看下面事例
void Printf(int* ptr, int sz){
int i ;
for(i=0;i<sz;i++){printf("%d",*(ptr+i));}
}
int main(){
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int* p = arr;
int sz = sizeof(arr)/sizeof(arr[0]);
Printf(p,sz);
return 0;
}
分析:
当我们要使用某个函数时,我们先要看这个函数的参数是什么,如果是一个一级指针,那么我们就可以传一个相同类型的一级指针,或者传一个类型相同的地址过来;
如:对于void test(char* p){…}这个函数而言,我们就可以给它传递一个指针
char ch= 'c'; char* p =&ch;test(p);
也可以直接传递test(&ch)
;
3.3二级指针传参
请看下面事例
void test(int** p2)
{
**p2=2;//修改指针指向地址内的值
}
int main(){
int a=10;
int* pa = &a;
int** ppa = &pa;//此时paa是一个二级指针,指向一级指针的指针,里面包含了一级指针的地址;
test(ppa);
test(&pa);
printf("第一次传二级指针和一级指针的地址时a的值:%d\n",a);
int* arr[10]={0};
test(arr);//传存放一级指针的数组
printf("第二次传一级指针的数组的地址时a的值:%d\n",a);
return 0
}
分析:
事例中:
(1)pa是一个一级指针,存放的是变量a的地址;
(2)paa是一个二级指针,指向一级指针的指针,里面存放了一级指针的地址;
(3)对一个形参为二级指针的函数,我们传参的时候可以传一个二级指针,也可以传一个一级指针的地址,或者传一个指针数组的数组名(指针数组的数组名就表示数组首元素地址,也就是指针数组里面的指针地址)
请看下面二级指针的图解:
四、感谢与预告
- 本次学习分享到此就结束了,如果本文对你有所帮助,请帮忙点赞+收藏,你的支持就是小编更新的最大动力!
【C语言进阶】⑤关于数组传参和指针传参辨析相关推荐
- 【C语言进阶】数组、指针、函数——传参篇
目录 写在前面 一.数组传参 一维数组传参 二维数组传参 二.指针参数 一级指针传参 二级指针传参 三.函数传参 四.看懂代码 写在最后 写在前面 上篇文章介绍了指针数组和数组指针,有兴趣的小伙伴可以 ...
- 指针-数组传参,指针传参
目录 数组传参 一维数组 二维数组 指针传参 一级指针 二级指针 一个特殊的二级指针 数组传参 一维数组 我们把传入一维数组时输入的是数组名,数组名是一个指向首元素的指针 那么在函数接收时,只需要保证 ...
- c++ 引用传参和指针传参的区别
概念 指针从本质上讲是一个变量,变量的值是另一个变量的地址,指针在逻辑上是独立的,它可以被改变的,包括指针变量的值(所指向的地址)和指针变量的值对应的内存中的数据(所指向地址中所存放的数据). 引用从 ...
- 一篇让你弄明白C语言指针传参和数组传参~
文章目录 前言 ⭐️指针传参和数组传参 ⭐️一维数组传参 ⭐️一级指针传参 ⭐️一道经典的指针传参相关题目 ⭐️二维数组传参 ⭐️函数指针!!! ⭐️一个有趣的代码!(*(void( * )())0) ...
- C语言 | 进阶之路第一关
目录 前言 - 文章概述 深入剖析数据在内存中的存储 数据的类型 整型在内存中的存储 浮点型在内存中的存储 指针进阶 字符指针 指针数组 数组指针 数组传参和指针传参 函数指针 函数指针数组 指向函数 ...
- C语言进阶-高阶指针
目录 前言 字符指针 指针数组 数组指针 &数组名VS数组名 数组指针的使用 数组参数.指针参数 一维数组传参 二维数组传参 一级指针传参 二级指针传参 函数指针 函数指针数组 指向函数指针数 ...
- c语言 字符串和数组指针,C语言数组与指针一本道来
数组与指针.png 指针的基础 注意本节内容可能在gcc下不能完成编译,请切换到Windows平台,使用dev-cpp或其他 指针本质上也是一个变量 指针要占用一定的内存空间(任何类型的指针的内存大小 ...
- 17.C语言进阶——深度理解指针
指针进阶 1. 字符指针 常见情况 在指针的类型中我们知道有一种指针类型为字符指针 char* ; 一般使用: int main() {char ch = 'w';char *pc = &ch ...
- 【C语言进阶】指针(进阶2)
目录 回顾: 数组参数.指针参数 一维数组传参 二维参数传参 一级指针传参 二级指针传参 回顾: 前面关于指针的内容我们已经学习了指针数组和数组指针我们来一起看看下面的代码的意思 int arr[5] ...
最新文章
- 小程序地图多个 circles 使用demo
- 右边补0 润乾报表_关于润乾报表的补充说明 -
- Arduino各开发板针脚示意图
- 用python画皮卡丘画法-python turtle绘图库绘制【皮卡丘】源码
- [翻译]Triggerless design.md
- 反思深度思考:预热[准备] 高密度[压力专注] 辨真伪[冷静分析] 反推[灵活] 结构化[全局]
- 计算机操作系统第三章知识点,深入理解计算机操作系统第三章家庭作业
- mysql在线快速修改密码_MySQL修改密码的几种方式
- 为什么程序员的社会地位不高?
- (王道408考研数据结构)第四章串-第二节:串的模式匹配算法(朴素和KMP)
- 正则表达式与python re
- 直观简洁,轻易吸睛!促销海报模板
- “火星人”马斯克推论:世界或是被编码而成,上帝可能是个程序员!
- 【java】swing编写窗体
- python_argparse简介
- 洛谷2678跳石头----二分答案入门
- 深度学习处理概率分布中常用的函数
- 大学生简单个人静态HTML网页设计作品 DIV布局个人介绍网页模板代码 DW学生个人网站制作成品下载
- 新版抖音二维码生成工具源码+实测可用
- 华东师范 2018年 研究生复试上机题解合集
热门文章
- [题目解析]乐乐的数字
- easyUI 正则表达式验证
- RFC2833 - 用于DTMF数字信号、电话音和电话信号的RTP负载格式
- LeetCode—5757. 矩阵中最大的三个菱形和(Get Biggest ...)[中等]—分析及代码(Java)
- 使用华为光猫ONT使能工具后,本地主机如何通过Telnet登录光猫进行配置
- MT4电脑版软件下载前后有哪些注意事项?
- 做个程序员到底好不好
- Kubernetes 污点和容忍
- dubbo 中文官网
- 飞机大战之六:敌机爆炸(碰撞检测)