文章目录
一、复习(函数的声明和定义)
1.单个文件
一般我们在写函数时,直接将函数写出来就使用了
比如:判断某一年是否为闰年
int is_leap_year(int y){
if((y%4==0&&y%100!=0)||y%400==0)
return 1;
else
return 0;
}
#include <stdio.h>
int main(){
int year;
scanf("%d",&year);
int t=is_leap_year(year);
if(t==1)
printf("%d is a leap year.",year);
else
printf("%d is not a leap year.",year);
return 0;
}
int is_leap_year ( int y ) { ......}是函数的定义部分;
int t = is _ leap _ year (year)是函数的调用部分;
在这种情况下,函数的定义放在函数调用前是没有声明问题的。
但如果我们将函数的定义放在函数的调用后,如下:
#include <stdio.h>
int main(){
int year;
scanf("%d",&year);
int t=is_leap_year(year);
if(t==1)
printf("%d is a leap year.",year);
else
printf("%d is not a leap year.",year);
return 0;
}
int is_leap_year(int y){
if((y%4==0&&y%100!=0)||y%400==0)
return 1;
else
return 0;
}
在编译器上就会出现警告信息:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int is_leap_year(int y); //函数的声明
int main() {
int year;
scanf("%d", &year);
int t = is_leap_year(year);
//函数的调用
if (t == 1)
printf("%d is a leap year.", year);
else
printf("%d is not a leap year.", year);
return 0;
}
//函数的定义
int is_leap_year(int y) {
if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)
return 1;
else
return 0;
}
函数的调用一定要满足:先声明后使用
函数的定义也是一种特殊的声明,所以函数定义放在函数调用前也是可以的。
2.多个文件
一般在企业在我们写代码的时候,代码可能比较多,不会将所有的代码放在一个文件中,我们往往根据程序的功能,将代码拆分在多个文件中。
如:
add.c
// 函数的定义
int add ( int x , int y );
{
return x+y ;
}
add.h
// 函数的声明
int add ( int x , int y ) ;
test.c
#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;
}
运行结果:
注:在多个文件的工程中
.c——源文件,函数的定义在源文件中;
.h——头文件,函数的声明,类型的声明放在头文件中;
二、static和extern的用法
1.简单介绍
static 和 extern 都是C语言中的关键字。
static 是静态的意思,可以用来:
- 修饰局部变量
- 修饰全局变量
- 修饰函数
extern 用来 声明外部符号
在说明static和extern的用法之前,简单介绍一下 :作用域和生命周期。
作用域 :
一段代码中所用到的名字并不总是有效的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
- 局部变量的作用域是变量所在的局部范围。
- 全局变量的作用域是整个工程(项目)。
生命周期是指变量的创建(申请内存)到变量的销毁(收回内存)之间的一个时间段
- 局部变量的生命周期:进入作用域变量创建,生命周期开始,出作用域生命周期结束
- 全局变量的生命周期:整个程序的生命周期
2.static和extern的用法
2.1 static修饰局部变量
代码1:
#include <stdio.h>
void test(){
int a=2;
a++;
printf("%d\n",a);
}
int main(){
int i;
for(i=0;i<5;i++){
test();
}
return 0;
}
此时代码运行结果为:
代码2:
#include <stdio.h>
void test(){
static int a=2;
a++;
printf("%d\n",a);
}
int main(){
int i;
for(i=0;i<5;i++){
test();
}
return 0;
}
运行结果:
代码1的test函数中的局部变量a是每次进入test函数先创建变量(生命周期开始)并赋值为2,然后++,再打印,出函数的时候生命周期将要结束(释放内存)。
代码2中,a有累加的效果,其实test函数中的a创建好后,出函数的时候是不会销毁的,重新进入函数也就不会重新创建变量,直接上次累积的数值继续计算。
结论:static修饰局部变量改变了变量的生命周期,生命周期改变的本质是改变了变量的存储类型,本来一个局部变量是存储在内存的栈区的,但是被static修饰后存储到了静态区。存储在静态区的变量和全局变量是一样的,生命周期和程序的生命周期一样了,只有程序结束,变量才销毁,内存才回收。但是作用域不变。
如果某一个变量出了函数后,我们还想保留值,等下次进入函数继续使用,就可以使用static修饰。
2.2 static修饰全局变量
代码1:
add.c
int year=2018;
test.c
#include <stdio.h>
extern int year;
int main(){
printf("%d\n",year);
return 0;
}
代码2:
add.c
static int year=2024;
test.c
#include <stdio.h>
extern int year;
int main(){
printf("%d\n",year);
return 0;
}
以上两个代码,代码1运行正确,结果为2018;而代码2会出现编译错误(链接性错误)。
extern是用来声明外部符号的,如果一个全局的符号在A文件中定义,在B文件中想使用,就可以使用extern进行声明,然后使用。
原因:
全局变量是具有外部链接属性的,哎外部的文件中想十一月,只要适当的声明就可以使用;但是被static修饰后,外部链接就变成了内部链接属性,其他.c文件无法使用。
如果一个全局变量,只想在所在的源文件内部使用,不行被其他文件发现,就可以用static修饰
2.3 static修饰函数
add.c
int add(int x,int y){
return x+y;
}
test.c
#include <stdio.h>
extern int add(int x,int y)
int main(){
printf("%d\n",add(2,3));
return 0;
}
其实static修饰函数和static修饰全局变量是一样的,一个函数在整个工程都可以使用,被static修饰后,只能在本文件内部使用,其他文件无法正常的链接使用了。