目录
一、什么是函数
函数分为库函数和自定义函数
库函数分为:IO函数、字符串操作函数、字符操作函数、内存操作函数、时间/日期函数、数学函数、其他库函数。
二、库函数
1、库函数的来源
库函数不是由C语言提供的,而是由C语言标准约定好2中的内容,然后由编译器的厂商提供的。
2、C语言标准规定:
函数的功能
函数名
参数
返回值类型
3、C语言的常用库函数
IO函数
字符串操作函数
字符操作函数
内存操作函数
时间/日期函数
数学函数
其它库函数
4、使用库函数的案例(我们在写代码的时候经常的在使用)
#include<stdio.h>
#include<math.h>
int main()
{
//pow函数的示例,pow函数的功能是求某一个数的某一次方
//格式:double pow(double num1,double num2)
//意思:求num1的num2次方,返回一个double类型的数字
int a = (int)pow(2,5);
printf("%d\n",a);
return 0;
}
#include<stdio.h>
#include<string.h>
int main()
{
//strcpy函数的示例,strcpy函数的功能是拷贝字符串
//格式:char* strcpy(char* destination,const char* source)
//意思:将source的字符串内容拷贝到destination中,并且返回destination的起始地址
char arr[] = "xxxxxxxxxxxxx";
char ch[] = "abcdefg";
strcpy(arr,ch);
printf("%s\n",arr);
return 0;
}
#include<stdio.h>
#include<string.h>
int main()
{
//memset函数的示例,memset的作用是将某部分内存中存储的数变为指定值
//语法:void* memset ( void * ptr, int value, size_t num )
//意思:将ptr地址开始的num个字节设置为value
char ch[] = "abcdefghijk";
memset(ch,'s',6);
printf("%s\n",ch);
return 0;
}
三、自定义函数(函数设计应该追求高内聚低耦合):
1、格式:
函数的返回类型 函数名(函数参数)
{
函数体;
}
2、函数的参数
①实际参数(实参):真实传给函数的值叫做实参。实参可以是变量、常量、表达式、函数。无论它们是什么形式,在函数调用时都必须有明确的值,以便传给形参。
②形式参数(形参):函数后面括号里面的变量叫做形参。只有当函数被调用时形参才会被创建,当函数调用完成后立刻被销毁。
3、函数的调用
①传值调用:函数的形参和实参占有不同的内存块,对形参的修改不会影响实参。
②传址调用:把函数外创建的变量地址传给函数,使函数内的操作可以影响函数外的变量。
☆函数调用的时候,将实参传递给形参。
☆形参是实参的一份临时拷贝
☆对形参的修改,不会改变实参
辨析:
int max(int* p1, int* p2)
{
}
int main()
{
int* p1;
int* p2;
printf("%d\n",max(p1,p2));
return 0;
}
这里依然是传值调用,因为p1和p2中虽然存储的是地址,但是p1和p2依旧是变量,函数没法改变p1和p2的值。这里要辨析明白,传的地址不一定是传址调用。
4、函数的嵌套调用和链式访问
嵌套调用:一个函数调用另一个函数在本函数中使用(但是,不可以在一个函数中定义另一个函数)。
链式访问:把一个函数的返回值作为一个函数的参数。
如:printf("%d",printf("%d",printf("%d",43)));
打印结果是:4321
原因是printf这个函数的返回值是屏幕上所打印的字符的数量(空格也算一个字符)。
5、函数的声明和定义
函数声明:①告诉编译器有一个函数,函数的参数类型、返回类型及函数名。声明的义务只是告知,有没有不重要。
②要满足先声明后使用。
③函数声明一般放在头文件中。
★函数的声明要在使用之前,可以放在所有函数外,也可以放在需要调用函数的函数中。
导入静态库
#pragma comment(lib,文件名)
函数的定义:①函数的具体实现,交代函数的功能。
②函数的定义是最强有力的函数声明
6、函数的递归
①定义:一个过程或函数在其定义或说明中直接或间接的调用自己的一种方法。
递归的主要思考方式是把大事化小。
②递归的两个必要条件:
<1>存在限制条件,当满足这个限制条件的时候,递归便不再继续。
<2>每次递归调用之后都越来越接近这个限制条件。
递归要满足这两个条件,但是满足这两个条件不一定会正确。比如可能会栈溢出。
内存分为三个区:栈区、堆区、静态区。
栈区:存放局部变量、函数形参和函数返回值等临时变量。
堆区:用于动态内存分配。
静态区:存放全局变量和静态变量。
★递归层次不能太深。
③递归与迭代
循环是一种迭代
注意:一个函数如果不设置返回类型,默认返回整型。
四、练习
1、写一个函数判断一个数是不是素数 √
2、写一个函数判断一年是不是闰年 √
3、写一个函数,查找一个有序数组中的某一个数,用二分查找 √
优化:int mid=(left+right)/2 可能left+right的和会超出int的范围,因此造成错误。
优化为:int mid=left+(right-left)/2
4、写一个函数,每调用一次函数,使num+1; √
☆补充:
<1>布尔类型:bool 需要引入头文件#include<stdbool.h>
<2>为了方便,我们可以在头文件所在的文件中创建我们自己的头文件,然后将我们常用的头文件全部添加进去,我们以后写代码的时候就可以只写一个我们自己的头文件。但是这种方法有利有弊。