举例sqrt代码语言cAI代码解释double sqrt (double x); //sqrt 是函数名 //x是函数的参数表⽰调⽤sqrt函数需要传递⼀个double类型的值 //double的返回值类型表⽰函数计算的结果是double类型的值2.2.1功能通过C的官网来查找我们可以看到这个库函数的功能如下图2.2.2头文件包含库函数是在标准库中对应的头⽂件中声明的所以库函数的使用必须包含对应的头文件不包含是可能会出现⼀些问题的。比如sqrt这个库函数必须包含math.h这个头文件。2.2.3实践sqrt库函数的实现示例代码语言cAI代码解释# includestdio.h # includemath.h int main() { double s 25.0; double n sqrt(s); printf(%lf\n, n); return 0; }运行结果如下图2.2.4库函数文档的一般格式1、函数原型2、函数功能的介绍3、参数和返回类型说明4、代码举例5、代码输出6、相关知识链接三、自定义函数了解了库函数我们可以了解一下自定义函数自定义函数的出现为程序员写的代码创造了更多的可能。下面来介绍自定义函数。3.1函数的语法形式自定义函数的语法形式和库函数相似形式如下代码语言cAI代码解释ret_type fun_name(形式参数) { }注ret_type 是函数返回类型fun_name 是函数名括号中放的是形式参数{ }括起来的是函数体函数通常会输入一些值然后函数内的计算来得出结果。ret_type 是⽤来表⽰函数计算结果的类型有时候返回类型可以是void 表示什么都不返回。fun_name是为了方便使用函数函数有了名字方便调用所以函数名尽量要根据函数的功能起的有意义。函数的参数可以是void 明确表示函数没有参数。如果有参数要交代清楚参数的类型和名字以及参数个数。{ }括起来的部分被称为函数体函数体就是完成计算的过程。3.2自定义函数的实例通过上面我们了解到自定义函数的语法形式以及注意事项和作用我们下面来举一些示例例写一个加法函数完成2个整型变量的加法操作。代码语言cAI代码解释#include stdio.h int Add(int x, int y) { int z x y; return z;//这个代码块可改为return xy; } int main() { int a 0; int b 0; scanf(%d %d, a, b); int c Add(a, b); printf(c %d, c); return 0; }在VS上运行的话会出现scanf报错问题可以查看我前面的文章来解决可永久解决这个问题。四、形参和实参接下来我们来看看形参和实参我们先看看前面写的代码。代码语言cAI代码解释#include stdio.h int Add(int x, int y) { int z x y; return z;//这个代码块可改为return xy; } int main() { int a 0; int b 0; scanf(%d %d, a, b); int c Add(a, b); printf(c %d, c); return 0; }4.1实参在写完Add函数后我们要使用的话就必须去调用它并且给它传入自己想要给的参数Add函数写完后在main函数中调用在调用的时候会传两个参数a,b而这两个参数(a,b)就是实参实际参数。实际参数就是真实传递给函数的参数。注实参调用函数时传递给函数的参数就是实参实际参数。4.2形参在写Add函数时函数名Add后括号中x,y就是形式参数简称形参。注形参函数定义中函数名后边的括号中的参数就是形式参数简称形参。为什么叫形式参数实际上如果只是定义了Add 后的括号中写的x和y称为形式参数简Add 函数⽽不去调⽤的话Add 函数的参数x和y只是形式上存在的不会向内存申请空间不会真实存在的所以叫形式参数。形式参数只有在函数被调⽤的过程中为了存放实参传递过来的值才向内存申请空间这个过程就是形参的实例化。4.3形参与实参的关系实参传递给形参他们之间是有关系的但是形参和实参是各自独立的内存空间。下面用调试来看形参和实参的关系代码如下代码语言cAI代码解释#include stdio.h int Add(int x, int y) { int z 0; z x y; return z; } int main() { int a 0; int b 0; //输⼊ scanf(%d %d, a, b); //调⽤加法函数完成a和b的相加 //求和的结果放在r中 int r Add(a, b); //输出 printf(%d\n, r); return 0; }通过调试可以看到x和y得到了a和b的值但是x和y的地址和a和b的地址是不⼀样的所以我们可以理解为形参是实参的⼀份临时拷贝。注1.实参和形参是不同的内存空间对形参的修改不会影响实参。2.实参是形参的一份临时拷贝。五、return语句在C语言中经常会遇到return语句return语句我们要注意以下几点1、return后边可以是⼀个数值也可以是⼀个表达式如果是表达式则先执⾏表达式再返回表达式的结果。2、 return后边也可以什么都没有直接写return; 这种写法适合函数返回类型是void的情况。3、 return返回的值和函数返回类型不⼀致系统会⾃动将返回的值隐式转换为函数的返回类型。4、 return语句执⾏后函数就彻底返回后边的代码不再执⾏。5、如果函数中存在if等分⽀的语句则要保证每种情况下都有return返回否则会出现编译错误。六、数组做函数参数代码语言cAI代码解释#include stdio.h void set_arr(int arr[],int sz) { int i 0; for(i 0;i sz;i) { arr[i] -1; } } void print_arr(int arr[],int sz) { int i 0; for(i 0;i sz;i) { printf(%d,arr[i]); } printf(\n); } int main() { int arr[10] {1,2,3,4,5,6,7,8,9,10}; //写一个函数将arr数组的内容全改为-1 int sz sizeof(arr)/sizeof(arr[0]); print_arr(arr,sz); set_arr(arr,sz); //写一个函数将arr数组的内容全部打印出来 print_arr(arr,sz); return 0; }上述代码中利用arr数组做为为set_arr和printf_arr的参数。重点①函数的形式参数要和函数的实参个数匹配。②函数的实参是数组形参也是可以写成数组形式的。③形参如果是一维数组数组大小可以省略不写。④形参如果是二维数组行可以省略但是列不能省略。⑤数组传参形参是不会创建新的数组的。⑥形参操作的数组和实参的数组是同一个数组。自行实现函数的打印代码如下代码语言cAI代码解释#include stdio.h void Print(int brr[][5],int r,int c) { int i 0; for(i 0; i r; i) { int j 0; for(j 0;j c;j) { printf(%d,brr[i][j]); } printf(\n); } } int main() { int arr[3][5] {{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7}}; Print(arr,3,5); return 0; }七、嵌套调用和链式访问注函数可以嵌套调用但是不能嵌套定义。7.1嵌套调用嵌套调⽤就是函数之间的互相调⽤。我们来计算某年某月有多少天is_leap_year()根据年份确定是否是闰年。get_days_of_month()调⽤is_leap_year确定是否是闰年后再根据月计算这个⽉的天数。代码语言cAI代码解释#include stdio.h int is_leap_year(int y) { if(((y%40)(y%100!0))||(y%4000)) return 1; else return 0; } int get_days_of_month(int y, int m) { int days[] {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int day days[m]; if (is_leap_year(y) m 2) day 1; return day; } int main() { int y 0; int m 0; scanf(%d %d, y, m); int d get_days_of_month(y, m); printf(%d\n, d); return 0; }main 函数调⽤scanf 、 printf 、get_days_of_month 。get_days_of_month 函数调⽤is_leap_year。7.2链式访问所谓链式访问就是将⼀个函数的返回值作为另外⼀个函数的参数像链条⼀样将函数串起来就是函数的链式访问。例子如下把strlen函数的返回值做为printf的参数这样一串串起来的就是链式访问。代码语言cAI代码解释#include stdio.h int main() { printf(%d\n, strlen(abcdef));//链式访问 return 0; }那么我们了解了链式访问后看看下面代码来想想其运行结果是什么代码语言cAI代码解释#include stdio.h int main() { printf(%d, printf(%d, printf(%d, 43)));//43 2 1 return 0; }我们先看看printf的返回值如下:代码语言cAI代码解释int printf ( const char * format, ... );在C语言官网上查找printf的返回值解释如下图注printf函数返回的是打印在屏幕上的字符的个数。由此可见printf在打印43后返回2再打印出来2返回1最后打印1。八、函数的声明和定义8.1单个文件函数的声明——是在告诉编译器有一个函数叫什么参数是什么返回类型是什么。例子判断这一年是否为闰年。代码语言cAI代码解释#include stdio.h int is_leap_year(int y); int main() { int y 0; scanf(%d,y); int r is_leap_year(y);//函数的调用 if(r 1) printf(Yes\n); else printf(NO\n); return 0; } //函数的定义 int is_leap_year(int y) { if(((y % 4 0) (y % 100 ! 0)) || (y % 400 0)) return 1; else return 0; }注先声明后定义定义是一种特定的声明。如果后定义并且不在前面声明那就会出错代码如下代码语言cAI代码解释#include stdio.h int main() { int y 0; scanf(%d,y); int r is_leap_year(y);//函数的调用 if(r 1) printf(Yes\n); else printf(NO\n); return 0; } //函数的定义 int is_leap_year(int y) { if(((y % 4 0) (y % 100 ! 0)) || (y % 400 0)) return 1; else return 0; }编译器vs就会报错如下图8.2多个文件⼀般在企业中我们写代码时候代码可能比较多不会将所有的代码都放在⼀个文件中我们往往会根据程序的功能将代码拆分6放在多个文件中。⼀般情况下函数的声明、类型的声明放在头⽂件.h中函数的实现是放在源文件.c文件中。代码如下add.c中代码语言cAI代码解释//函数的定义 int Add(int x, int y) { return xy; }acc.h中代码语言cAI代码解释#pragma once //函数的声明 int Add(int x, int y);test.c中代码语言cAI代码解释#include stdio.h #include add.h int main() { int a 10; int b 20; //函数调⽤ int c Add(a, b); printf(%d\n, c); return 0; }运行结果如下图总结函数的定义放在源文件中函数的声明、类型的声明放在头文件中这里可以做到代码的隐藏静态库。8.3 static 和externstatic 和extern 都是C语⾔中的关键字。static 是静态的的意思可以用来1.修饰局部变量2.修饰全局变量3.修饰函数extern 是用来声明外部符号的。作用域是程序设计概念通常来说一段程序代码中所用到的名字并不总是有效可用的而限定这个名字的可⽤性的代码范围就是这个名字的作用域。即哪里能使用那里就是作用域①局部变量的作用域是变量所在的局部范围。②全局变量的作用域是整个工程项目。生命周期指的是变量的创建(申请内存)到变量的销毁(收回内存)之间的⼀个时间段。①局部变量的生命周期是进⼊作用域变量创建生命周期开始出作用域生命周期结束。②全局变量的生命周期是整个程序的生命周期。8.3.1static修饰局部变量先看如下代码的运行结果有static的代码代码语言cAI代码解释#include stdio.h void test() { static int a 2; a; printf(%d\n,a); } int main() { int i 0; for(i 0;i 5;i) { test(); } return 0; }无static的代码代码语言cAI代码解释#include stdio.h void test() { int a 2; a; printf(%d\n,a); } int main() { int i 0; for(i 0;i 5;i) { test(); } return 0; }由结果运行图我们可以得出以下结论static修饰局部变量改变了变量的生命周期生命周期改变的本质是改变了变量的存储类型本来一个局部变量是存储在内存的栈区的但是被static修饰后存储到了静态区。存储在静态区的变量和全局变量一样的生命周期就和程序的生命周期一样了只有程序结束变量才销毁内存才回收但是作用域不变的。使用建议未来⼀个变量出了函数后我们还想保留值等下次进⼊函数继续使用就可以使用static修饰。8.3.2static修饰全局变量extern 是用来声明外部符号的如果⼀个全局的符号在A文件中定义的在B⽂件中想使用就可以使用extern进行声明然后使用。第一种没加static修饰全局变量的add.c代码语言cAI代码解释int g_val 2024;test.c代码语言cAI代码解释#include stdio.h extern int g_val; int main() { printf(%d\n, g_val); return 0; }运行结果第一种可以正常运行。第二种加了static修饰全局变量的add.c代码语言cAI代码解释static int g_val 2018;test.c代码语言cAI代码解释#include stdio.h extern int g_val; int main() { printf(%d\n, g_val); return 0; }运行结果第二种会出现链接错误。总结全局变量是具有外部链接属性的但是被static修饰后外部链接属性就会变成了内部链接属性只能在自己所在的.c文件中使用其他.c文件无法使用即使声明也无法正常使用。使用建议一个全局变量被static修饰使得这个全局变量只能在本源文件内使用不能在其他源文件内使用。.C每一个源文件都是单独编译的。