单个文件中-函数的声明和定义:
#define _CRT_SECURE_NO_WARNINGS //函数的调用必需满足先声明后使用--->这样子函数的定义可以写到后面编译器不会发出警告 //闰年的判断 //是闰年返回1 //不是闰年返回0 //函数声明 int is_leap_year(int y); #include<stdio.h> int main() { int y = 0; scanf("%d", &y); //判断是否是闰年 if (is_leap_year(y)) { printf("%d是闰年\n",y); } else { printf("%d不是闰年\n",y); } return 0; } //函数定义 int is_leap_year(int y) { if (y % 400 == 0 || ((y % 4 == 0 )&& (y % 100 != 0))) return 1; else return 0; }
函数的调用必需满足先声明后使用--->这样子函数的定义可以写到后面编译器不会发出警告
函数的定义也是一种特殊的声明,所以可以把定义放前面,如下代码示例:
//函数定义 int is_leap_year(int y) { if (y % 400 == 0 || ((y % 4 == 0) && (y % 100 != 0))) return 1; else return 0; } #include<stdio.h> int main() { int y = 0; scanf("%d", &y); //判断是否是闰年 if (is_leap_year(y)) { printf("%d是闰年\n", y); } else { printf("%d不是闰年\n", y); } return 0; }
多个文件中-函数的声明和定义:
就是将一个程序拆成多个文件进行分别加工,就好比计算机的实现可以将加减乘除分别拆成4个模块进行分别编写---->可以用于隐藏代码的实现,会在后面出一起相关的文章.
函数的声明(#.... .h)、类型的声明放在头⽂件(.h)中.
库函数相关头文件: C 标准库头文件 - cppreference.com
函数的实现是放在原⽂件(.c)⽂件中。
如下:
Static和Extern:
作用域(scope):一个变量在哪里可以使用,哪里就是他的作用域.
1. 局部变量的作⽤域是变量所在的局部范围。大括号里面定义的变量
2. 全局变量的作⽤域是整个⼯程。大括号外面定义的变量
Extern:是用来声明外部符号的
生命周期指的是变量的创建(申请内存)到变量的销毁(收回内存)之间的⼀个时间段。
1. 局部变量的⽣命周期是:进⼊作⽤域⽣命周期开始,出作⽤域⽣命周期结束。
2. 全局变量的⽣命周期是:整个程序的⽣命周期。
Static是 静态的 的意思,可以⽤来:
• 修饰局部变量
• 修饰全局变量
• 修饰函数
static修饰局部变量:
//代码1: #include<stdio.h> void test() { int a = 0; a++; printf("%d ", a); } int main() { int i = 0; for (i = 0; i < 5; i++) { test(); } return 0;; }
//代码2: #include<stdio.h> void test() { static int a = 0;//局部变量被static修饰时 a++; printf("%d ", a); } int main() { int i = 0; for (i = 0; i < 5; i++) { test(); } return 0;; }
//代码3: #include<stdio.h> int a = 0;//a为全局变量时 void test() { a++; printf("%d ", a); } int main() { int i = 0; for (i = 0; i < 5; i++) { test(); } return 0;; }
对比代码1和代码2的效果,理解static修饰局部变量的意义:
代码1的test函数中的局部变量i是每次进⼊test函数先创建变量(⽣命周期开始)并赋值为0,然后 ++,再打印,出函数的时候变量⽣命周期将要结束(释放内存)即a=1被摧毁。
代码2,我们从输出结果来看,i的值有累加的效果,其实test函数中的i创建好后,出函数的时候是 不会销毁的,重新进⼊函数也就不会重新创建变量,直接上次累积的数值继续计算。
结论:static修饰局部变量改变了变量的⽣命周期,⽣命周期改变的本质是改变了变量的存储类型,本来⼀个局部变量是存储在内存的栈区的,但是被 static修饰后存储到了 静态区。存储在 静态区的变量和全局变量是 ⼀样的, ⽣命周期就和程序的⽣命周期⼀样了,只有 程序结束,变量才销毁,内存才回收。但是作⽤域不变的。
使用场景:未来⼀个变量出了函数后,我们还想保留值,等下次进⼊函数继续使⽤,就可以使⽤static 修饰。
static修饰全局变量:
extern 是⽤来声明外部符号的,如果⼀个全局的符号在A⽂件中定义的,在B⽂件中想使⽤,就可以使 ⽤extern进⾏声明,然后使⽤。
如图所示:代码1正常,代码2在编译的时候会出现连接性错误。
全局变量是具有外部链接属性的
static修饰全局变量以后,外部连接属性变成了内部连接属性
其它.c文件再也无法使用,但是再它原来那个文件还是能作为全局变量继续使用.
使用场景:如果⼀个全局变量,只想在所在的源⽂件内部使⽤,不想被其他⽂件发现,就可以使⽤ static修饰。
static修饰函数:
代码1是能够正常运⾏的,但是代码2就出现了链接错误。
static 修饰函数和static修饰全局变量是⼀模⼀样的,⼀个函数在整个⼯程都可以使⽤,被static修饰后,只能在本⽂件内部使⽤,其他⽂件⽆法正常的链接使⽤了。
本质是因为函数默认是具有外部链接属性,使得函数在整个⼯程中只要适当的声 明就可以被使⽤。但是被static修饰后变成了内部链接属性,使得函数只能在⾃⼰所在源⽂件内部使
⽤。
使用场景:⼀个函数只想在所在的源⽂件内部使⽤,不想被其他源⽂件使⽤,就可以使⽤static修饰。