8.1单个文件
⼀般我们在使⽤函数的时候,直接将函数写出来就使⽤了。
⽐如:我们要写⼀个函数判断⼀年是否是闰年。
#include <stido.h>
//判断⼀年是不是闰年
int is_leap_year(int y)
{
if(((y%4==0)&&(y%100!=0)) || (y%400==0))
return 1;
else
return 0;
}
int main()
{
int y = 0;
scanf("%d", &y);
int r = is_leap_year(y);
if(r == 1)
printf("闰年\n");
else
printf("⾮闰年\n");
return 0;
}
这种场景下是函数的定义在函数调⽤之前是没有问题。
如果我们将函数的定义放在函数的调⽤后边:
#include <stido.h>
int main()
{
int y = 0;
scanf("%d", &y);
int r = is_leap_year(y);
if(r == 1)
printf("闰年\n");
else
printf("⾮闰年\n");
return 0;
}
//判断⼀年是不是闰年
int is_leap_year(int y)
{
if(((y%4==0)&&(y%100!=0)) || (y%400==0))
return 1;
else
return 0;
}
这个代码在VS2022上编译,会出现警告信息,这是因为C语⾔编译器对源代码进⾏编译的时候,从第⼀行往下扫描的,当遇到第7行的is_leap_year 函数调⽤的时候,并没有发现前⾯is_leap_year的定义,就报出了上述的警告。
那么怎么解决这个问题呢?就是函数调⽤之前先声明⼀下is_leap_year这个函数,声明函数只要交代清楚:函数名,函数的返回类型和函数的参数。
int is_leap_year(int y);这就是函数声明,函数声明中参数只保留类型,省略掉名字也是可以的。
那么代码会变成:
#include <stido.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");
else
printf("⾮闰年\n");
return 0;
}
//判断⼀年是不是闰年
int is_leap_year(int y)
{
if(((y%4==0)&&(y%100!=0)) || (y%400==0))
return 1;
else
return 0;
}
先声明后使用,函数的定义也是一种特殊的声明,所以如果函数在调用之前也是可以的。
8.2多个文件
⼀般情况下,函数的声明、类型的声明放在头⽂件(.h)中,函数的实现是放在原⽂件(.c)⽂件中。
如:
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;
}
8.3static和extern
static是 静态的 的意思,可以⽤来:
修饰局部变量 ;
修饰全局变量 ;·
修饰函数 ;
extern是⽤来声明外部符号的。
生命周期&作用域:
作用域与生命周期是两个完全不同的概念。作用域是一个静态概念,旨在编译源程序的时候用到。一个标识符的作用域指在源文件中该标识符能够独立的合法出现的区域,生命周期则是一个程序运行时的概念,它指的是变量在整个程序中载入到结束运行的过程中存在的时间周期。函数和数据类型是静态的概念,所以没有生命周期的说法,它们从编译、程序的运行到结束是一直存在的。
8.3.1static修饰局部变量
static修饰局部变量改变了变量的⽣命周期,⽣命周期改变的本质是改变了变量的存储类型,本 来⼀个局部变量是存储在内存的栈区的,但是被static修饰后存储到了静态区。存储在静态区的变量和全局变量是⼀样的,⽣命周期就和程序的⽣命周期⼀样了,只有程序结束,变量才销毁,内存才回 收。但是作⽤域不变的。
8.3.2static修饰全局变量
⼀个全局变量被static修饰,使得这个全局变量只能在本源⽂件内使⽤,不能在其他源⽂件内使⽤。本质原因是全局变量默认是具有外部链接属性的,在外部的⽂件中想使⽤,只要适当的声明就可以使 ⽤;但是全局变量被static修饰之后,外部链接属性就变成了内部链接属性,只能在⾃⼰所在的源⽂件 内部使⽤了,其他源⽂件,即使声明了,也是⽆法正常使⽤的。
如果⼀个全局变量,只想在所在的源⽂件内部使⽤,不想被其他⽂件发现,就可以使⽤ static修饰。
8.3.3static修饰函数
与修饰全局变量本质上一致
⼀个函数只想在所在的源⽂件内部使⽤,不想被其他源⽂件使⽤,就可以使⽤static修饰。