目录

写在前面

一、数组传参

一维数组传参

二维数组传参

二、指针参数

一级指针传参

二级指针传参

三、函数传参

四、看懂代码

写在最后


写在前面

上篇文章介绍了指针数组和数组指针,有兴趣的小伙伴可以看一看。

在写程序时,有时难免要把数组或指针传给函数,我们又该怎么写参数呢?开门见山,有两种方法:

  1. 照着原函数写
  2. 用指针接收

一、数组传参

一维数组传参

法一:test1和test2的前两项是照着原函数写

法二:test1和test2的第三项是用指针接收

#include<stdio.h>
void test1(int arr[])//正确
{}
void test1(int arr[10])//正确
{}
void test1(int* arr)//正确
{}
void test2(int* arr[])//正确
{}
void test2(int* arr[10])//正确
{}
void test2(int **arr)//正确,用来存放一级指针变量的地址
{}
int main()
{int arr1[10]={0};int* arr2[10]={0};test1(arr1);test2(arr2);return 0;} 

上面的6种写法  来接收函数传来的地址  均是正确的。

难点解释:

第一种理解方式:test2 中 arr2是首元素地址,也就是一个整形指针的地址,我们当然可以用一个二级指针来接受一级指针的地址,

另一种理解方式:int** arr2  ,写参数时可以理解成 (int*) (*arr2),前一部分可以理解成原函数的类型,后一部分可以理解成一个新命名的指针。

知识补充:

test1函数中,传来的是数组的首元素地址,所以我们可以定义int arr[ ],int arr[一个数字],数组大小可以不写,因为在32位平台,数组首元素大小,也就是指针大小固定4个字节,写不写都没有意义,但写的话就不要写错,以免引起误导。


二维数组传参

法一:第一个test是照着原函数写

法二:后面4个是用指针接收

#include<stdio.h>
void test(int arr[3][5])//正确
{}
void test(int *arr)//错误,整形指针不能接收数组的地址
{}
void test(int* arr[5])//错误,指针数组
{}
void test(int (*arr)[5])//正确,数组指针 可以存放数组的地址
{}
void test(int **arr)//错误,用来存放一级指针变量的地址
{}
int main()
{int arr[3][5]={0};test(arr);return 0;} 

知识补充:

二维数组的参数中,第一个行参数可以不写,但第二个列参数必须写!

二、指针参数

一级指针传参

#include<stdio.h>
void test(int* p)//正确
{}
int main()
{int a=0;int* p=&a;test(&a);//正确 test(p);// 正确 return 0;} 

把int 类型改为 char 类型亦是如此


二级指针传参

有问有答:形参是二级指针,能传什么实参呢?

  1. 一级指针变量的地址
  2. 二级指针变量本身
  3. 存放一级指针的数组名,也就是指针数组名
#include<stdio.h>
void test(int **p)
{}
int main()
{int a=0;int* p=&a;int** pp=&p; test(&p);test(pp); //两个test等价 return 0;} 

三、函数传参

基本格式:函数返回类型+指针变量+函数类型

#include<stdio.h>
int add(int x,int y)
{int z=0;z=x+y;return z;
}
int main()
{int a=3;int b=5;printf("%d",add(a,b));return 0;
}//上面的函数是普通的传参,下面是与其对照的函数传参#include<stdio.h>
int add(int x,int y)
{int z=0;z=x+y;return z;
}
int main()
{int a=3;int b=5;int (*p)(int,int)=add;printf("%d",(*p)(3,5));return 0;} 

难点解析:

  • int* p(int,int)=add;  如果我们这样写,就是这样理解的:p是函数名(int ,int)表示add函数的两个整形参数,int* 就是返回类型,这显然与我们的预期,用指针存放add函数的地址,有出入。
  • int (*p)(int,int)=add;用来接收函数地址,其基本格式为函数返回类型+指针变量+函数类型=函数名
  1. (*p)就可以表明p是指针变量。
  2. (int,int)表示add函数的两个整形参数。
  3. int 表示add函数的返回类型。
  • (*p)(3,5)  是对函数的调用: p存放函数地址,*p就是add函数,等价于add(3,5)

add(3,5)      ⇔       (*p)(3,5)      ⇔      p(3,5)      ⇔ (**p)(3,5)  实际上*再多就没有意义了

我们进行一个简单应用:打印结果为hello world

#include<stdio.h>
void print(char* str)
{printf("%s",str);
}
int main()
{void (*p)(char*)=print;(*p)("hello world");return 0;} 

四、看懂代码

细细理解下面的代码你会对指针有更加深刻的理解,不了解函数指针基本格式的,可以再看看上面。

一、(*(void(*)())0)()——调用0地址处的该函数(无参无返回类型)

拆分:(*   (  void(*)() )0  )     ()       

  • void(*)()  是函数指针类型
  •  ()0  是强制类型转换,例如(int)5.0,就是5,在这里就是将0强制类型转换为函数地址
  • *(  void(*)() )0    0既然是地址,那么*解引用之后,就找到了函数
  • 最后面的()是对函数的调用,并且没有传参

翻译解释:把0强制类型转换为一个函数指针类型,该指针指向哪个函数是无参返回类型是void,当0变成一个函数地址之后,对它进行解引用操作,去调用以0为地址处的该函数。


二、void(* signal(int, void(*)(int) ) )(int)

拆分:void(* signal(int, void(*)(int) ) )(int)

signal(参数一, 参数二),随后再把这一部分套进函数参数中就完成复原。

翻译解释:void(* signal(int, void(*)(int) ) )(int)  大概意思就是自定义函数signal里面定义两个参数,一个为int类型,一个为函数指针类型(该函数指针指向的函数的参数为int,返回类型是void), signal函数的返回类型也是一个函数指针,该函数指向的函数参数为int,返回类型为void

写在最后

创作不易,还希望各位大佬支持!

【C语言进阶】数组、指针、函数——传参篇相关推荐

  1. C语言与java中函数传参比较

    C语言与java中函数传参比较 首先先说结论:C语言中参数传递有值传递,地址传递,引用传递.但java中的参数传递只有值传递 1.C语言中的参数传递 1>值传递 值传递非常好理解,其实就是对函数 ...

  2. C语言 指针在函数传参中的使用

    int add(int a, int b)   //函数传参的时候使用了int整型数据,本身是数值类型.实际调用该函数时,实参将自己拷贝一份,并将拷贝传递给形参进行运算.实参自己实际是不参与运算的.所 ...

  3. 指针数组的初始化和遍历,并且通过for循环方式、函数传参方式进行指针数组的遍历...

    1 /************************************************************************* 2 > File Name: messa ...

  4. linux文件编程(3)—— main函数传参、myCp(配置成环境变量)、修改配置文件、整数和结构体数组写到文件

    参考:linux文件编程(3)-- 文件编程的简单应用:myCp.修改配置文件 作者:丶PURSUING 发布时间: 2021-04-09 23:45:05 网址:https://blog.csdn. ...

  5. linux-c之函数(函数指针、函数传参、命令行参数)

    一.函数的定义与声明.调用 #include <stdio.h>int add(int a,int b);//函数声明int main() {int a = 5;int b= 6;int ...

  6. C/C++ 一维数组的传参/一级指针的传参 二维数组的传参/二级指针的传参 三维数组的传参/三级指针的传参 方法总结分析终极篇

    序 最近复习c/c++数组的传参,发现了一些问题,下面是一些总结和思考 正文 一维数组的传参/一级指针的传参/普通指针 在理解指针的基础上,一维数组的指针传递很简单,我们知道数组的数组名就是这个数组首 ...

  7. 图解C语言中数组指针、指针数组、函数指针、函数指针数组、指向函数指针数组的指针

    关于C语言中数组指针.函数指针.指针数组.函数指针数组.指向函数指针数组的指针一直比较绕,稍微整理一下. 到底是指针还是数组? 其实到底是指针还是数组还是看变量名与[]先结合还是*先结合.我们知道C语 ...

  8. c语言冒泡排序数组指针,c语言冒泡排序,指针,数组

    冒泡排序算法的运作如下: 比较相邻的元素.如果第一个比第二个大,就交换他们两个. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的数. 针对所有的元素重复 ...

  9. 从getmemery()函数看内存管理、函数传参等一系列问题

    在C 面试题目中,会经常出现getmemery()函数的改错题,比如下面这道题, 例一:代码如下: [cpp] view plaincopy #include <stdio.h> char ...

最新文章

  1. iOS11和iPhone X的适配
  2. EventBus3.0源码解析
  3. IOS开发之自定义Button(集成三种回调模式)
  4. P1351-联合权值【树形结构】
  5. 八个被现代科学证实的古老信条
  6. 如何判断注册用户是否已经存在(membership验证)
  7. html清楚css的影响,08、清除浮动的影响.html
  8. 河南省初三计算机考试题库,河南省计算机等级考试—VB题库
  9. 前馈神经网络对mnist数据集实战
  10. 大数据Hadoop生态圈-组件介绍
  11. Apple EDI X12 业务报文解析(一)—— 850采购订单
  12. 计算平均成绩和总成绩
  13. Java返回报文有单双引号_Spring MVC 响应结果有反斜杠转义字符+双引号
  14. nmap学习记录(未完待续)
  15. python中重采样的时间间隔与等距,resample,periods
  16. python3 psycopg2查询PostgreSQL返回字典
  17. 零基础学习CANoe Panel(6)—— 开关/显示控件(Switch/Indicator)
  18. ubuntu20.04lts初体验
  19. 一口气笑穿极简印度史,简到崩溃,笑到流泪(一)
  20. 极路由云平台倒闭,路由器免插件离线ROOT方法

热门文章

  1. outlook2013配置
  2. Oracle 取余函数
  3. Web3的先锋兵:虚拟人
  4. 记使用腾讯TIM开发聊天通讯遇到的问题及解决方案
  5. python 矩阵元素查找位置函数_Python中二维数组中非零元素位置的快速查找方法...
  6. OSPF —— 多区域部署 + ABR + ASBR + 路由重分发
  7. 【附源码】Java计算机毕业设计家政管理系统(程序+LW+部署)
  8. Apache Velocity 模板语言 特殊字符${ $!{ 原样输出问题 转义符 # ! 无效
  9. 工作和生活遇到的Windows常见需求 跨局域网共享文件 网页加载慢更换DNS
  10. Android脑图--Android动画