前言
友友们大家好啊!今天我又与大家分享C语言的函数部分了。
1函数是什么?
大家可能对数学中的函数是比较熟悉的,那C语言中的函数又是什么呢?
维基百科中对函数的定义:子程序
1 在计算机科学中,子程序(英语:Subroutine, procedure, function, routine, method, subprogram, callable unit),是一个大型程序中的某部分代码, 由一个或多个语句块组 成。它负责完成某项特定任务,而且相较于其他代 码,具备相对的独立性。
2 一般会有输入参数并有返回值,提供对过程的封装和细节的隐藏。这些代码通常被集成为软 件库。
简单理解:C语言中的函数就是可以实现某个功能的代码块,有一定的独立性,一般有返回值。
2 C语言中函数的分类:
库函数
自定义函数
2.1 库函数
简单来说就是C语言提供给你用的一些函数,放在某个库中存放起来。
注意:使用库函数,必须包含 #include 对应的头文件。
下面是C语言的一些库
库函数的学习
需要全部记住吗?No
需要学会查询工具的使用:MSDN(Microsoft Developer Network)(这是个工具需要下载)
www.cplusplus.com
http://en.cppreference.com(英文版)
http://zh.cppreference.com(中文版)
这些是学习库函数的网站的链接,大家有遇到的不懂的函数都可以去里面查,本人用到最多的是第一个工具MSDN他能方便你查找库函数。
2.2自定义函数
库函数不可能包含你要实现功能的所有函数,所以在C语言中函数是可以定义的。
自定义函数的框架:
ret_type fun_name( para1, * )
{
statement;//语句项
}
ret_type 返回类型
fun_name 函数名
para1 函数参数
为了方便介绍我们先定义个加法函数。
#include<stdio.h> //定义加法函数 int Add(int x, int y) { int sum = x + y; return sum; } int main() { int a = 0; int b = 0; scanf("%d%d", &a, &b); int ret = Add(a,b); printf("sum = %d\n", ret); return 0; }
3. 函数的参数
3.1 实际参数(实参)
真实传给函数的参数,叫实参。
实参可以是:常量、变量、表达式、函数等。
无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。
3.2 形式参数(形参):
形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内存单元),所以叫形式参数。
形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效。
3.3详解函数的参数
我们从上面了解到实参就是实际传给变量的,是一确定的值,而形参是用来接收实参的,在函数中调用完就会销毁。为了深刻理解我们写一个函数可以交换两个整形变量的内容。
#include<stdio.h> void Swap1(int x, int y) { int tmp = x; x = y; y = tmp; } void Swap2(int* px, int* py) { int tmp = *px; *px = *py; *py = tmp; } int main() { int num1 = 10; int num2 = 20; printf("交换前:num1 = %d,num2 = %d\n", num1, num2); Swap1(num1, num2); printf("交换后:num1 = %d,num2 = %d\n", num1, num2); Swap2(&num1, &num2); printf("交换后:num1 = %d,num2 = %d\n", num1, num2); return 0; }
从打印的结果来看只有Swap2( )函数完成了功能要求,为什么会这样呢?
分析:我们可以看到Swap1( )和Swap2( )函数的本质是区别是函数1传的是值而函数2传过去的是这个值的地址。
我们调试起来看看:
从中我们可以看到函数1中x和y确实交换了,但为什么num1和num2没交换呢?
我们取出num1和num2及x与y的地址来看
大家可以看到为了存储形参x和y又重新创建了地址,地址上分别存了10和20,当我们在函数中更改了x和y是不能影响num1和num2的。(也就是说函数的形参和实参没有建立起联系来)
在来看函数2的传参数方式
我们可以看到px和py地址上存放是num1和num2的地址,当我们对地址*引用便可以找到num1和num2,这样使得形参和实参变的有联系起来,所以在函数2中对px和py的改变会影响nun1和nun2。
总结函数的传值调用与传址调用
1 函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。
2 传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
3 这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。
4 函数的嵌套调用和链式访问
4.1 函数的嵌套调用
就是函数可以根据需要组合在一起,也就是相互调用。
举例:
#include<stdio.h> void test2() { int i = 0; for (i = 0;i < 3;i++) { printf("hehe\n"); } } void test1() { test2(); } int main() { test1(); return 0; }
从代码中我们可以看出,在主函数中我们调用了test1,在test1中我们又调用了test2,所以在屏幕中我们打印了3个hehe,这便是函数的嵌套调用。
注意:函数可以嵌套调用,但是不能嵌套定义。
4.2 链式访问
就是把一个函数的返回值作为另外一个函数的参数。
举例:
#include<stdio.h> int main() { printf("%d", printf("%d", printf("%d", 'a'))); return 0; }
看到这里大家可能会有疑问,为什么打印的是9721让我们在MSDN(查看库函数的工具)看看printf的返回值是什么吧。
大意说:这些函数中的每一个都返回打印的字符数,如果发生错误,则返回负值。
分析:
我们可以看到printf3他以%d打印一个字符a,a的ASCll为97所以上屏幕打印了97,printf2是printf3作为链式访问,而printf3的返回值为2,所以屏幕中又打印了2。最后的printf1是以printf2作为链访问的,printf2打印了2所以他的返回值为1即屏幕最后打印1。(为了方便叙述我们把printf函数从左到右编号1,2,3)
结束语
今天的分享就到这里结束了,函数部分未完待续!希望对大家有帮助,如果大家觉的有用就来个三连,谢谢大家 。