参数和指针|学习笔记

简介: 快速学习参数和指针

开发者学堂课程【你的第一门 C 语言课参数和指针】学习笔记,与课程紧密联系,让用户快速学习知识

课程地址:https://developer.aliyun.com/learning/course/444/detail/5495


参数和指针


简介:

一、参数和返回值

二、形参和实参

三、传值和传址

四、传数组

五、可变参数

 

一、参数和返回值

1.参数的用法和作用

函数是一种封装的方法。函数的设计遵从一个函数仅实现一个功能的原则,便可化繁为简,将复杂的程序拆解开,变成一个个独立的功能。每个功能使用单个函数实现。

函数定义时通过参数列表以指定函数的数量和类型,前者使得后者更加灵活。传入的参数使得函数拥有更为丰富的功能。同时,函数应支持个性化定制

2. 类型名

函数实现功能通常需要反馈结果,但实际操作中并不一定出现,故需要设定一个返回值以观察函数调用是否成功,或者出现了何种问题。若函数的确不需要返回值,则可以使用 void 以表示不返回。

定义函数时,已经确定了参数的数量和类型,但参数数量是可变的。

 

二、形参和实参

1.定义

形参:形式参数

实参;实际参数

2.举例

#include

int sum(int, int);

int sum(int x,int y)

{

return (x + y);

}

int main()

{

sum(3, 5);

return 0 ;

}

其中,int x,int y 为形参。其仅作为占位符,并无实际的数值。而在函数被调用期间,传与其一个实际的数值,例如3, 5,此为实际数值,被称为实参。

形参与实参均用于数据传输,当函数发生调用时实参的数值将传递给形参,此种传输具有单向性,即不能讲形参的值传输给实参。形参变量定义时仅作为一个占位符,提示需要留存变量并保留空间,并无实际数据的传输,数值仍为随机。只有在函数调用时,数值的位置才会真正生成空间、分配内存。而当函数调用结束后,其又会立刻释放内存。故,形参变量仅在函数内部有效。

 

三、传值和传址

指针是一个变量,可以通过参数传递给函数。

1.引进指针参数的实际意义

(1).不使用指针的示例:

#include

void swap(int x,int y);

void swap(int x,int y)

{

int temp

printf(“In sawp,互换前:x=%d,y=%d\n”,x,y);

temp=x  

x=y

y=temp  /*两数交换所需要的中间值*/

printf(“In sawp,互换后:x=%d,y=%d\n”,x,y);

}

int main( )

{

int x=3,y=5;

printf(“In main,互换前:x=%d,y=%d\n”,x,y);

swap(x,y); /*swap:互相交换的含义*/

printf(“In main,互换后:x=%d,y=%d\n”,x,y);

return0;

}

得到结果:

[fishc@bogon sle29]$ gcc testl.c && . /a . out

in main,互换前:x=3,y=3;

in swap,互换前:x=3,y=5;

in swap,互换前:x=5,y=3;

in main,互换前:x=3,y=5;

fishc@bogon sle29] $   //结果与预料相同

(2).使用指针的示例:

[fishc@bogon sle29] $ cp test1.c test2.c

[fishc@bogon sle29] $ vi test2.c

#include

void swap(int *x,int *y);  //指针x,y存放的是数值,对其都要进行解引用

void swap(int *x,int *y)

{

int temp

printf(“In sawp,互换前:x=%d,y=%d\n”,*x,*y);

temp=*x  

*x=*y

*y=temp

printf(“In sawp,互换后:x=%d,y=%d\n”,*x,*y);

}

int main( )

{

int x=3,y=5;

printf(“In main,互换前:x=%d,y=%d\n”,x,y);

swap(&x,&y); //指针中存放的必须为地址

printf(“In main,互换后:x=%d,y=%d\n”,x,y);

return0;

}y

得到结果:

[fishc@bogon sle29]$ gcc test2.c && . /a . out

in main,互换前:x=3,y=3;

in swap,互换前:x=3,y=5;

in swap,互换前:x=5,y=3;

in main,互换前:x=5,y=3;

fishc@bogon sle29] $

(3).结论

当不使用指针时,函数内部无法改变实参的值,即内部 (swap) 互换之后,在 main 中的值仍未改变。

由于 C 语言中每个函数都有独立的作用域,即每个函数的内部都是互相独立的,他们的作用旨在函数内部生效,不同函数之间不能直接访问对方的变量。例如 main和 swap 两个作用域中的x,y并不冲突,是不同的两组变量。

2.使用指针能改变的原因

指针中存放的是别人的地址,例如经 main 函数中的 x,y 两个地址传递给形参,则两个形参函数 x,y 即是对两个变量 x,y 的引用。引用后相当于将其地址搬到另一处,直接进行互换。

实现了传值和传址的根本区别。


四、传数组

1.示例一

[fishc@bogon sle29]$ gcc test3.c

#include

void get_array(int a[10]); //array:数组

void get_array(int a[10])

{

int i;

for (i=0;i<10;i++)

{

printf(“a[%d] = %d\n”,i,a[i]);

}

}

int main()

{

int a[10]={1,2,3,4,5,6,7,8,9,0};

get_arrayp{a}

return 0 ;

}  

查看打印结果:

[fishc@bogon sle29]$ gcc test3.c && ./a.out

a[0] = 1

a[1] = 2

a[2] = 3

a[3] = 4

a[4] = 5

a[5] = 6

a[6] = 7

a[7] = 8

a[8] = 9

a[9] = 0

[fishc@bogon s1e29]$

在此基础上修改代码:

#include

void get_array(int a[10]);

void get_array(int a[10])

{

int i;

a[5] = 520;

for (i=0;i<10;i++)

{

printf(“a[%d] = %d\n”,i,a[i]);

}

}

int main()

{

int a[10]={1,2,3,4,5,6,7,8,9,0};

int i;

get_array(a);

printf(*在main函数中再打印一次...\n*);

for (i=0;i<10;i++)

{

printf(“a[%d] = %d\n”,i,a[i]);  

}

return 0 ;

}

若在调用时将整个数组传递进形参中,则两方的 a 同样是独立开的。此情况下的变量将不会被互相修改到。但实际情况如下:

[fishc@bogon sle29]$ gcc test3.c && ./a.out

a[0] = 1

a[1] = 2

a[2] = 3

a[3] = 4

a[4] = 5

a[5] = 520

a[6] = 7

a[7] = 8

a[8] = 9

a[9] = 0

在main函数里边再打印一次......

a[0] = 1

a[1] = 2

a[2] = 3

a[3] = 4

a[4] = 5

a[5] = 520

a[6] = 7

a[7] = 8

a[8] = 9

a[9] = 0

[fishc@bogon s1e29]$

此时 fishc 和 main 数组的函数都被改动,说明并不存在将整个数组作为参数传递的方式。接受的仅是地址本身。

2.示例二

[fishc@bogon sle29]$ gcc test4.c

#include

void get_array(int a[10]); //由于并不是将一个数组传递给过来,此处仅作为验证进行

void get_array(int a[10])

{

printf(“sizeof b: %d\n”,sizeof(b));

}

int main()

{

int a[10] = {1,2,3,4,5,6,7,8,9,0}

printf(“sizeof a: %d\n”,sizeof(a));

查看结果:

[fishc@bogon sle29]$ gcc test4.c && ./a.out

sizeof a:40  //a是41个元素,每一个整型变量在变异系统中占4个字节,总量为10x4=40字节

sizeof b:4 //仅作为地址,故只占有一个地址应有的尺寸,即4个字节

[fishc@bogon sle29]$

 

五、可变参数

1.定义

可变参数的实现需要包含头文件,即 stdarg.h,头文件中需要四个元素

#include

一个类型:

va_list-定义字符指针的类型

三个宏:

va_start-对字符指针进行计算

va_arg

va_end

其中,va即variable-argument的缩写

2.示例

[fishc@bogon sle29]$ gcc test4.c

#include

#include

int sum(int n...)  //...表示数目不确定

int sum(int n...)

{

int i,sum = 0;

va_list vap;  //定义参数列表

va_start(vap,n);   //传入宏va_start

for (i = 0;i

{

sum +=va_arg(vap,int);  //利用va_arg获取每一个参数的值、类型

}

va_end(vap); //va_end关闭参数列表

return sum;

}

int main()

{

int result;    //接收返回的结果

result = sum(3,1,2,3);

printf(“result1 =%d\n”,result);

result = sum(53,1,2,3,4,5);

printf(“result2=%d\n”,result);

result = sum(6,3,-1,-2,4,99,100);

printf(“result3=%d\n”,result);

return 0;

}

查看结果:

[fishc@bogon sle29]$ gcc test5.c && ./a.out

result1 = 6

result2 = 15

result3 = 203

[fishc@bogon sle29]$

相关文章
|
存储 SQL 关系型数据库
MySQL请求使用union查询结果为空
MySQL请求使用union查询结果为空
|
Oracle 网络协议 关系型数据库
Oracle DataGuard主备切换之自动切换
Oracle DataGuard主备切换之自动切换
611 2
|
存储 SQL 机器学习/深度学习
通用数据湖仓一体架构正当时
通用数据湖仓一体架构正当时
227 2
|
消息中间件 缓存 前端开发
【架构设计】互联网架构项目架构演进以及三高设计概述
【架构设计】互联网架构项目架构演进以及三高设计概述
【架构设计】互联网架构项目架构演进以及三高设计概述
|
Cloud Native 云计算
《云原生架构白皮书2022年新版》电子版下载地址
如何更好地拥抱云计算、拥抱云原生架构、用技术加速创新,将成为企业数字化转型升级成功的关键。
428 0
《云原生架构白皮书2022年新版》电子版下载地址
|
存储 人工智能 Linux
2022最新C语言指针超详解(大学看这个就够了,0基础也能看懂)(2)
10.数组指针 1、二维数组 2、数组指针的概念: 3、数组指针的定义方法: 4、各种数组指针的定义: 5、三维数组指针,加 1 后指向下个三维数组 6、四维数组指针,加 1 后指向下个四维数组,以此类推。。。。 7、注意: 8、数组名字取地址:变成 数组指针 9、数组名字和指针变量的区别: 10、数组指针取* 11.指针和函数的关系 指针作为函数的参数 12.指针作为函数的返回值 13.指针保存函数的地址(函数指针) 1、函数指针的概念: 2、函数指针的用处: 3、函数指针变量的定义 4、调用函数的方法 5、函数指针数组 6、函数指针应用举例
2022最新C语言指针超详解(大学看这个就够了,0基础也能看懂)(2)
|
存储 机器学习/深度学习 人工智能
本地部署开源大模型的完整教程:LangChain + Streamlit+ Llama
在过去的几个月里,大型语言模型(llm)获得了极大的关注,这些模型创造了令人兴奋的前景,特别是对于从事聊天机器人、个人助理和内容创作的开发人员。
9127 1
|
弹性计算 运维 容灾
阿里云使用体验
经过进一步的体验云服务器我感受到阿里云提供的性能卓越、稳定可靠、弹性扩展的IaaS(Infrastructure as a Service)级别云计算服务。云服务器ECS免去了采购IT硬件的前期准备,就像是使用水、电、天然气等公共资源一样便捷、高效地使用服务器,实现计算资源的即开即用和弹性伸缩,在使用期间给阿里云我最大的印象就是方便,快捷。使用界面简单明了,通过不断地尝试,我了解到了更多的特殊概念,专业名词,也了解到了如快照等容灾备份能力的实际用途,现实生活中,如果我们的电脑磁盘出现了故障,数据出现了损坏就无能为力了,或者只能够找专业的人把数据能够找回来,但是不能够保证说所有的数据都能找回来。
|
存储 人工智能 Cloud Native
高性能存储SIG月度动态:io_uring支持nvme直通,DSMS完成开发测试
Cloud Kernel SIG 月度动态送达,一键了解 5 月各项目进展。
|
机器学习/深度学习 资源调度 JavaScript
机器学习概念漂移检测方法(Aporia)
目前,有多种技术可用于机器学习检测概念漂移的方法。熟悉这些检测方法是为每个漂移和模型使用正确度量的关键。 在本文章中,回顾了四种类型的检测方法:统计、统计过程控制、基于时间窗口和上下文方法。