1.当函数的返回值类型是void时,return后边可以什么都不写,直接写return;当return的返回的值和函数返回类型不一致时,系统会自动将返回的值隐式转换为函数的返回类型;return语句执行后,函数就彻底返回,后边的代码不再执行;如果函数中存在if等分支的语句,则要保证每种情况下都有return返回,否则会出现编译错误;函数的返回类型如果什么都不写,默认函数的返回类型是int。
2.函数的实参是数组的话,形参也是可以写成数组形式的;形参如果是一维数组,数组大小可以忽略不写;形参如果是二维数组,行可以省略,但是列不能省略;数组传参,形参是不会创建新的数组的,形参操作的数组和实参的数组是同一个数组。一个数组作为函数实参的例子如下:
#include<stdio.h>
void arr_set(int arr[], int len)
{
int i = 0;
for (i = 0; i < len; i++)
{
arr[i] = -1;
}
}
void arr_print(int arr[],int len)
{
int i = 0;
for (i = 0; i < len; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int len = sizeof(arr) / sizeof(arr[0]);
arr_set(arr, len);
arr_print(arr, len);
return 0;
}
3.函数之间可以嵌套调用,但是函数之间不能够嵌套定义。
下面是一个函数嵌套调用的例子,用来计算某年某月有多少天,在get_year_month函数中嵌套调用了is_runnian函数
#include<stdio.h>
int is_runnian(int y)
{
if (((y % 4 == 0) && (y % 100 != 0)) || y % 400 == 0)
{
return 1;
}
else
return 0;
}
int get_year_month(int y, int m)
{
int months[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
int num = months[m];
if (is_runnian(y) && m == 2)
{
num++;
return num;
}
else
{
return num;
}
}
int main()
{
int y = 0;
int m = 0;
scanf("%d%d", &y, &m);
int days = get_year_month(y, m);
printf("%d", days);
return 0;
}
4.链式访问就是将一个函数的返回值作为另外一个函数的参数,像链条一样将函数串起来,下面就是一个链式访问的例子:
int arr[]="abcdef";
printf("%d\n",strlen(arr));
printf函数返回的是打印在屏幕上的字符的个数
int main()
{
printf("%d", printf("%d", printf("%d", 43)));
return 0;
}
5.函数的调用一定要满足先声明后使用,函数的定义也是一种特殊的声明,所以函数定义放在调用之前也是可以的。
一般情况下函数的声明、类型的声明放在头文件(.h)中,函数的实现是放在源文件(.c)文件中
6.static和extern
static和extern都是c语言中的关键字,static是静态的意思,可以用来修饰局部变量、全局变量、函数;extern是用来声明外部符号的。
作用域:一段程序代码中所用到的名字并不总是有效可用的,而限定这个名字可用性的代码范围就是这个这个名字的作用域。局部变量的作用域是变量所在的局部范围,全局变量的作用域是整个工程(项目)。
生命周期:变量的创建(申请内存)到变量的销毁(收回内存)之间的一个时间段。
局部变量的生命周期:进入作用域变量创建,生命周期开始,出作用域生命周期结束。
全局变量的生命周期: 整个程序的生命周期。
static修饰局部变量:
左边图片中的代码中的test函数中局部变量i每次进入test函数先创建变量(生命周期开始)并赋值为0,然后++,再打印,结果一直为1,出test函数时候生命周期结束(释放内存)。
右边图片中的代码中的test函数中变量i在创建后不会销毁 ,重新进入函数后也不会重新创建变量,直接上次累计的数值继续计算。
原因:static修饰局部变量时,改变了局部变量的生命周期,原本存储在内存栈区的局部变量,被static修饰后存储到了静态区,于是就与全局变量一样,生命周期和程序的生命周期一样,程序结束,变量销毁,内存回收。注意,static不会改变变量的作用域。
使用建议:未来⼀个变量出了函数后,我们还想保留值,等下次进入函数继续使用,就可以使用static 修饰。
static修饰全局变量:
extern是用来声明外部符号的,如果⼀个全局的符号在A文件中定义的,在B文件中想使用,就可以使 用extern 进行声明,然后使用。
如在文件test.c中声明全局变量
int g_val = 2024;
如果想在文件main.c中使用该全局变量,用extern在main.c中声明即可
extern int g_val;
但是如果在test.c中用static修饰全局变量g_val,那么这个全局变量只能在本源文件内test.c中使用,不能在其他源文件中使用。
原因:全局变量在被static修饰后,外部链接属性就变成了内部链接属性,只能在自己所在的源文件内部使用了,其他源文件,即使声明了,也无法正常使用。
使用建议:如果⼀个全局变量,只想在所在的源文件内部使用,不想被其他文件发现,就可以使用 static修饰。
static修饰函数
在test.c存在函数
int Sub(int x,int y)
{
return x-y;
}
如果想在文件main.c中使用该函数,用extern在main.c中声明即可
extern int Sub(int x,int y)
但是如果在test.c中用static修饰函数Sub,那么这个函数只能在本源文件内test.c中使用,不能在其他源文件中使用,其他文件无法正常的链接使用。