文章目录
1. 函数的概念
C语言中函数就是执行某特定任务的一小段代码,主要分为库函数
和自定义函数
.
1.1 库函数
库函数就是C语言规定的标准库里的函数,例如printf输出、scanf输入函数,查看库函数→库函数相关文件
1.2 自定义函数
其实就是我们自己定义的函数,函数名尽量要有意义
这里的ADD就是我们定义的加法函数,使用自定义函数时,函数一定要放在函数调用前,如果想要将函数放在函数调用之后,那么要在调用前进行函数声明.
//函数
#include <stdio.h>
int ADD(int x, int y); //也可以写成int ADD(int , int );主要是声明有ADD这个函数,且两个参数都是int类型
int main()
{
int a = 7;
int b = 17;
int sum = ADD(a, b);
printf("%d\n", sum);
return 0;
}
int ADD(int x, int y)
{
return x + y;
}
2. 实参和形参
2.1 实参
int ADD(int x,int y)
{
return 0;
}
//
int sum = ADD(a,b);
实参就是真实传递给函数的参数,例如上面提到的代码int sum= ADD(a,b);
中的a和b就是实参
2.2 形参
int ADD(int x,int y)
{
return 0;
}
//
int sum = ADD(a,b);
上面提到的代码中,int ADD(int x,int y)
中的x和y就是形参,形参顾名思义,就是形式上存在的参数,如果我们没有去调用ADD这个函数,那么x和y两个形参也不会再内存中占用空间,只有当ADD函数被调用时,形参才会为了接收实参传过来的值而在内存中创建空间来进行存放.
2.3 实参和形参的关系
通过调试我们发现,实参a和b的值确实放进形参x和y里面了,但是实参和形参的地址却不同,说明在内存中重新为形参创建了空间来存放数值,因此也可以称形参就是实参的一份临时拷贝.
实参和形参名也可以相同。
3. 数组传参
创建一个arr[10]的整型数组,初始化数组为{1,2,3,4,5,6,7,8,9,10}
将数组的每个元素换成‘-1’
//数组传参
#include <stdio.h>
void set_arr(int arr[10], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
arr[i] = -1;
}
}
void print_arr(int arr[10], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%p\n", &arr[i]);
}
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < sz; i++)
{
printf("%p\n", &arr[i]);
}
printf("------------------\n");
set_arr(arr, sz);
print_arr(arr, sz);
return 0;
}
通过上图我们可以看出,数组在传参时,实参和形参中的数组元素的地址相同,说明数组在传参时并未创建新的数组,实参和形参中的数组是同一个.因此我们可以得出:
- 函数的实参和形参个数要匹配
- 函数的实参是数组,形参也可以写成数组形式
- 形参如果是一维数组,数组大小可以不写
- 形参如果是二维数组,行可以省略,列一定不能省略不写
- 数组传参,形参不会创建新的数组
- 形参的数组和实参的数组是同一个
4. return语句
- return语句后面可以跟数值或表达式,若跟表达式,则先计算表达式再返回
- 返回类型是void时,return后面可以什么也不跟
- 代码中if等多支语句时,要保证每种情况下都有return返回,防止报错
- return语句执行后会立即返回,不会再执行后面的语句.
5. 函数嵌套使用和链式访问
5.1 嵌套使用
- is_leap_year():根据年份确定是否是闰年
- get_days_of_month():调⽤is_leap_year确定是否是闰年后,再根据⽉计算这个⽉的天数
//计算某年某月有多少天
#include <stdio.h>
int is_leap_year(int a)
{
if ((a % 4 == 0) && (a / 100 != 0) || (a / 400 == 0))
return 1;
else
return 0;
}
int get_days_of_month(int a, int b)
{
int days[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };//由于数组下标从0开始,第一个元素初始化为0,方便对齐输入的年月份
int day = days[b];
//判断是否为瑞年,是则2月份+1
if (is_leap_year(a) && b == 2)
day += 1;
return day;
}
int main()
{
int a = 0; //年份
int b = 0; //月份
scanf("%d %d", &a, &b);
int num = get_days_of_month(a, b);
printf("%d\n", num);
return 0;
}
5.2 链式访问
链式访问就是把一个函数的返回值当成另一个函数的参数
猜一猜这段代码执行结果是什么呢?
#include <stdio.h>
int main()
{
printf("%d", printf("%d", printf("%d", 43)));
return 0;
}
这里主要了解一下printf函数也会返回一个参数,而printf函数返回的是它读取到的字符个数,第一个printf函数正常输出43,并且返回2,将返回值放到第二个printf函数里,变成printf(“%d”,printf(“%d”,2));这时候继续打印2,然后第二个printf函数返回1,变成printf(“%d”,1),打印1.
6. 关键字static和extern
在工程中常常会创建多个(.c)和(.h)文件中,通常函数定义放在(.c)文件,而声明函数放在(.h)文件.
static可以修饰局部变量、全局变量、函数.
- static修饰局部变量
- static修饰全局变量
- static修饰函数