影视网站seo是什么品牌
1.函数的概念
函数(function),有的地方翻译为子程序。C语言中的函数就是完成某项特定的任务的⼀段代码。C语言的程序其实是由无数个小的函数组合而成的,也可以说:⼀个大的计算任务可以分解成若⼲个较小的函数(对应较小的任务)完成。同时⼀个函数如果能完成某项特定任务的话,这个函数也是可以反复使用的,提升了软件的开发效率。
2.库函数
2.1:为了不再重复写常见的代码(如写一个函数按照某种格式在屏幕上打印信息、写一个函数求字符串的长度),提高程序员的开发效率,C语言标准(ANSI)规定了一些函数(每个函数都规定了函数名、返回值类型、形式参数以及函数功能),再由不同的编译器厂商根据该规定实现这些函数,提供给程序员使用。这些函数组成了一个函数库,称为标准库,这些函数就被称为库函数。 在这个基础上⼀些编译器厂商可能会额外扩展提供部分函数(这些函数其他编译器不一定支持)。
2.2:同⼀系列的库函数⼀般会声明在同⼀个头文件中(比如,与字符串相关的库函数的声明就在头文件string.h中)。使用库函数前,一定要包含对应的头文件(函数要先声明后使用,包含头文件就相当于函数的声明)。
2.3:C++中提供的库函数的链接
2.4:库函数对应的头文件链接
3.自定义函数
3.1:实参(实际参数)
#include <stdio.h>
int Add(int x, int y)
{return x + y;
}
int main()
{int a = 0;int b = 0;scanf("%d %d", &a, &b);int r = Add(a, b);printf("%d\n", r);return 0;
}
调用Add函数时,传递给函数的参数a和b,称为实际参数,简称实参。
3.2:形参(形式参数)
当函数未被调用时,并不会向栈区为函数的形参分配空间。只有当函数被调用时,才会在栈区为形参分配空间,用来存储实参传过来的值。
3.3:实参与形参的关系
形参只是接收了实参的值,但形参与实参的空间不一样的,形参值的改变并不会影响实参值的改变
4.return语句的几点注意事项
1.当函数的返回值类型是void时,可以不写return语句,或者写return ;表示不返回任何值)
2.return后边可以是⼀个数值,也可以是⼀个表达式,如果是表达式则先执行表达式,再返回表达式的结果。
3.return语句执行后,函数就彻底返回,后边的代码不再执行。
4.return返回的值和函数返回类型不⼀致,系统会自动将return返回的值隐式转换为函数的返回类型。(建议将函数的返回值与返回类型保持一致)
int test()
{int n = 1;if (n == 1)return 1.5;elsereturn -1.5;
}
int main()
{int r = test();//test函数返回的是1,而不是1.5printf("%d", r);//1return 0;
}
5.如果函数中存在if等分支的语句,则要保证每种情况下都有return返回,否则编译器可能会报警告(不是报错误)
6.C语言中,如果函数不写返回值类型,则编译器会默认为该函数的返回值类型是int,且这种写法是极不推荐的!!!。另外,在C++中,如果函数不写返回值类型,编译器将报错。
7.当函数写了返回值类型,但没有写return语句,则函数返回的是随机值(这种写法也极不推荐!!!)
double test()
{printf("hello\n");
}
int main()
{double r = test();printf("%lf", r);return 0;
}
5.数组做函数参数
5.1:数组传参(要理解透彻)
结合下面这幅图来理解
5.2:一维数组传参时,形参若写成数组的形式,数组的大小可以省略不写;二维数组传参时,形参若写成数组的形式,数组的行的大小可以省略不写,但列的大小必须写。
void print_arr(int arr1[][5], int r, int c)
{//第一个形参与int *arr1完全等价,本质都是用指针变量arr1来接收数组首元素的地址for (int i = 0; i < r; i++){for (int j = 0; j < c; j++){printf("%d ", arr1[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(arr, 3, 5);return 0;
}
6.函数的嵌套调用与链式访问
6.1:嵌套调用
6.1.1:何为嵌套调用?
如函数A中调用函数B,函数B中调用函数C
6.1.2:计算某年某⽉有多少天?
#include<stdio.h>
#include<stdbool.h>
bool is_leap_year(int y)//判断年份y是否是闰年
{if (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))return true;elsereturn false;
}
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;//闰年:2 月 29 天 ,平年:2 月 28 天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;
}
6.2:链式访问
6.2.1:何为链式访问?
将一个函数的返回值作为另外一个函数的参数,像链条一样将多个函数串接起来。
#include<string.h>
#include<stdio.h>
int main()
{printf("%zd\n", strlen("abcdef"));//将strlen函数的返回值作为printf的参数return 0;
}
6.2.2:printf函数的返回值是什么?
成功打印字符的个数
int main()
{int r = printf("%d\n", 112);printf("%d\n", r);//4 printf这个打印了112(三个字符)和一个换行符,因此它的返回值是4return 0;
}
6.2.3:下面这段有趣的代码的运行结果是什么?
int main()
{printf("%d", printf("%d", printf("%d", 43)));return 0;
}
7.函数的定义与声明
7.1:函数的定义与声明与调用之间的关系
a.函数必须先声明后使用。函数声明就是告诉编译器有这个函数的存在(以及这个函数的返回值类型是什么,名字是什么、参数的类型是什么)。
b.函数定义就是函数的实现。
c.如果函数定义写在函数调用之前,就可以直接调用该函数。因为函数定义是一种特殊的函数声明。
7.1.1:单个文件
在单个源文件中,若函数调用写在函数定义之前,进行函数声明时,不需要加extern关键字
#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("闰年\n");elseprintf("不是闰年\n");return 0;
}//判断⼀年是不是闰年
int is_leap_year(int y)
{if (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))return 1;elsereturn 0;
}
7.1.2:多个文件
a.⼀般在企业中写代码时候,代码可能比较多,不会将所有的代码都放在⼀个文件中。往往会根据程序的功能,将代码拆分放在多个文件中。一般情况下,头文件(.h文件)中写函数的声明(还可以类型的定义,如单链表中声明一个结构体类型,用来表示一个结点的结构),源文件(.c文件)中写函数的实现,当要使用该函数时,就只需要包含该头文件。包含自己写的头文件时用" ",包含C语言标准库提供的头文件时用< >
b.在源文件(.c文件)中包含头文件的本质是什么?
将头文件中的所有内容复制一份到该源文件中。
8.static(静态) 与extern(与"数据类型与变量"这篇博客中的第4点结合起来看)
8.1:静态区中数据的特点
全局变量、被static修饰的(局部变量、全局变量)都是存放在静态区中的。存放在静态区中的数据,代码在编译阶段就已经为这些数据分配空间了,也就是这些数据说在main函数执行前就已经有了,且这些数据的生命周期与整个工程生命一致。
8.2:static修饰局部变量
a.下面这两段代码的执行结果是什么?
代码1的执行结果是2 2 2 2 2
每当test函数被调用时,局部变量i就创建了,等调用结束时,i出了作用域就销毁了,等下一次调用test函数时,i又会重新创建。
代码2的执行结果是2 3 4 5 6
局部变量i被static修饰了,因此它是存放在静态区的,i在main函数执行前就已经被创建了,因此调用test函数时,static int i=0;这句代码不会被执行。i的作用域就是test函数的大括号中(并不是整个工程),但它出了作用域也不会被销毁,它的生命周期与整个程序的生命周期一致。每调用一次test函数,i的值都会在原来的基础上加1
b.static修饰局部变量的特点
被static修饰的局部变量,它的存储位置不再是栈区,而是静态区。因此它的生命周期与整个工程的生命周期一致(从main函数开始执行到return 0这段时间),但它的作用域依旧是所在的大括号内部。
c.什么时候使用static修饰局部变量?
未来⼀个变量出了函数后,我们还想保留它的值,等下次进入函数继续使用,就可以使用static修饰。
补充:
int main()
{for (int i = 0; i < 5; i++){int a = 4;a++;printf("%d ", a);}return 0;
}
//这里a创建并销毁了5次,每当打印完a的值后,a就销毁了
8.3:static修饰全局变量
a.全局变量具有外部链接属性。在一个源文件中定义的全局变量,若想在其他源文件中使用,只需要在该源文件中用extern声明就行了。
b.static修饰全局变量的特点
全局变量被static修饰后,它的外部链接属性就变成了内部链接属性。即使在其他源文件中用extern声明了也不能使用。
c.什么时候用static修饰全局变量?
如果⼀个全局变量,只想在它所在的源文件内部使用,其他源文件中无法使用,就可以使用static修饰。
8.4:static修饰函数
a. 函数具有外部链接属性。在一个源文件中定义的函数,若想在其他源文件中使用,只需要在该源文件中用extern声明就行了。
b.static修饰函数的特点
函数被static修饰后,它的外部链接属性就变成了内部链接属性。即使在其他源文件中用extern声明了也不能使用。
c.什么时候用static修饰函数?
如果⼀个函数,只想在它所在的源文件内部使用,其他源文件中无法使用,就可以使用static修饰。