目录
函数是什么?
在维基百科中对函数的定义:子程序
在计算机科学中,子程序是一个大型程序中的某部分代码,有一个或者多个语句块组成。它负责完成某项特定任务,而且相较于其他代码,具备相对的独立性。
一般会有输入参数并有返回值,提供对过程的封装和细节的隐藏。这些代码通常被集成为软件库。
C语言中函数的分类:
1.库函数
我们在开发过程中每个程序员都可能用得到的,为了支持可移植性和提高程序效率,所以C语言的基础库中提供了一系列类似的库函数,方便程序员进行软件开发。
比如我们经常使用的
scanf("",);
printf("");
sqrt();
....//等
要注意使用库函数必须要加上它的头文件,如果没有头文件,它是无法被调用的
例如:
#include<math.h>
#include<stdio.h>
int main()
{
int n=16;
printf("%d\n", sqrt(n));//sqrt()的头文件就是#include<math.h>
}
常用库函数有:
IO函数 字符串操作函数 字符操作函数 内存操作函数 时间/日期函数 数学函数 其他函数
2.自定义函数
何为自定义函数:自定义函数和库函数一样,有函数名,返回值类型和函数参数。但是不一样的是这些都是我们自己来设计的。
例如:
//求三个数中的最大值
#include<stdio.h>
int MAX(int x,int y,int z)
{
if(x>y)
{
if(x>z)
{
return x;
}
else
return z;
}
else
{
if(y>z)
{
return y;
}
else
return z;
}
}
int main()
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
int ret=0;
ret=MAX(a,b,c);
printf("%d\n",ret);
return 0;
}
在调用自定义函数的 时候要特别注意实参和形参的区别,比如下面这个例子
交换两个整形变量的内容:
#include<stdio.h>//形参
void swap(int x, int y)
{
int temp = 0;
temp = x;
x = y;
y = temp;
}
int main()
{
int a = 0;
int b = 0;
scanf("%d%d",&a,&b);
printf("交换前:a=%d b=%d\n", a, b);
swap(a,b);
printf("交换后:a=%d b=%d\n",a,b);
return 0;
}
//实参
void swap2(int* x, int* y)
{
int temp=0;
temp = *x;
*x = *y;
*y = temp;
}
int main()
{
int a = 0;
int b = 0;
scanf("%d%d",&a,&b);
printf("交换前:a=%d b=%d\n", a, b);
swap2(&a,&b);
printf("交换后:a=%d b=%d\n",a,b);
return 0;
}
其结果也不同:
1.
2.
为什么会造成这样两种不同的结果呢?其原因在于
swap 函数是传值调用,在最开始传过去的时候,它传过去的仅仅是数值,但是它们的空间不是共用的一个空间--->在一个函数变量被定义的时候,内存就单独为这个函数变量创建了一个独属于它的空间。
这个实质上是一个传值调用:函数的形参和实参分别占有不同的内存块,对形参的修改不会影响实参。
正因为这样它swap内完成交换的时候,因为他是没有返还值的函数,交换完了的数字不会返还到主函数里,所以对主函数没有影响,
而后面的 swap2 这个函数能够完成交换操作就在于,它们是用的同一个空间,swap2 函数接收的并不是一个数值,而是一个地址,通过这个地址来完成对原来的函数的操作,因为它们在一个空间内,改变的值也是一个空间的值,所以即便没有返回值也能完成主函数的要求。
实质上它是个传址调用:
传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。
所以我们可以简单的认为:形参实例化之后其实相当于实参的一份临时拷贝,而拷贝的内容却无法对原文件产生影响。
函数的调用
函数我们可以嵌套调用,但是不能嵌套定义。
我们把一个函数的返回值作为另外一个函数的参数的这种调用形式,成为链式访问
例如
printf("%d", printf("%d", printf("%d", 43)));
printf函数的返回值是打印在屏幕上字符的个数,所以结果是4321
函数的声明和定义
函数声明 就是告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但是具体是不是存在,函数声明决定不了。
函数的声明一般出现在函数的使用之前。要满足先声明后使用
函数的声明一般要放在头文件中
函数定义 是指函数的具体实现,交代函数的功能实现
例如
#include<stdio.h>
int Add(int x,int y)//函数的声明
int main()
{
int a,b;
scanf("%d%d",&a,&b);
int ret=Add(a,b);
printf("%d\n",ret);
return 0;
}
int Add(int x,int y)//函数的定义
{
return x+y;
}
也可以是这种写法:
这种分文件的书写形式虽然看起来麻烦,但是它也有优点
1.可以实现多人协作,加入要做一个计算器,那么把计算器的代码可以划分为主函数,加法模块,减法模块,乘法模块,除法模块五大板块,一个人要做五个,但是如果把他分文件就可以5个人一起来做,一人负责一块,极大地提高了效率
2.可以实现封装和隐藏
源文件在实现过程中会产生一个静态库,静态库里是二进制语言,隐藏了你原来的代码。
函数递归
什么是函数递归?程序调用自身的编程技巧叫做递归
递归是一种方法,他通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小问题来求解,往往只需要少量的程序就可以描述出解题过程所需的多次复杂计算,大大的减少了程序的代码量
例
#include <stdio.h>
void print(int n)
{
if(n>9)//递归停下来的判定条件
{
print(n/10);//通过n/10来改变n值,然后不断的调用自身来实现循环
}
printf("%d ", n%10);
}
int main()
{
int num = 1234;
print(num);
return 0;
}
感兴趣的朋友可以自己尝试一下用循环的方式去做这个逆向打印,相对来说是比较复杂的,要创建两个数组,一个数组进行收集数字,另一个数组则对这个数组里的数进行排序,然后打印
最后欢迎大佬前来斧正,觉得这篇文章对你有用的朋友还望能够一键三连加关注