前言
为了更好地理解static,这里有必要先补充一下前置知识:
1.作用域(scope)
简单来说就是限定某个名字或变量可用性的代码范围
①局部变量的作用域是变量所在的局部范围。
② 全局变量的作用域是整个工程(项目)。
2.生命周期
简单来说就是 变量的创建(申请内存)——>变量的销毁(收回内存) 之间的⼀个时间段。
①局部变量的生命周期:进入作用域变量创建,生命周期开始,出作用域生命周期结束。
②全局变量的生命周期:整个程序的生命周期。
1.extern(外部)
如果一个符号具有外部链接属性,如:全局变量、函数。在外部的文件中想使用,只要适当的声明就可以使用,此时就可以使用extern声明。如:
一个全局的符号在A文件中被定义,在b文件中想要使用,在使用前就可以使用extern声明该全局符号。
test1.c文件
int Moment=0;
test2.c文件
#include <stdio.h>
extern int Moment=0;
int main()
{
printf("%d\n", Moment);
return 0;
}
2.static(静态的)
(1)static修饰局部变量
#include <stdio.h>
void test()
{
static int i = 0;//static修饰局部变量
i++;
printf("%d ", i);
}
int main()
{
int i = 0;
for(i=0; i<5; i++)
{
test();
}
return 0;
}
未用static修饰前:test函数中的局部变量 i 是每次进入test函数都要先创建变量(生命周期开始)并赋值为0,然后 ++,再打印,出函数的时候变量生命周期结束(释放内存)。
使用static修饰后:,i 的值有累加的效果,test函数中的 i 创建好后,出函数的时候不会销毁,重新进入函数也就不会重新创建变量,直接从上次累积的数值继续计算。
注:
static修饰局部变量改变了变量的生命周期,本质上是改变了变量的存储类型,原本局部变量存储在内存的栈区,但是被static修饰后存储到了静态区,存储在静态区的变量和全局变量生命周期相同,但是作用域不变。
(2)static修饰全局变量
为了方便理解,将上面extern处代码截图至此处:
代码1
代码2
test3.c文件(static修饰)
static int Moment=0;
test4.c文件
#include <stdio.h>
extern int Moment=0;
int main()
{
printf("%d\n", Moment);
return 0;
}
结论:代码1正常运行,代码2在编译的时候会出现链接性错误。
解释:
全局变量默认具有外部链接属性,在外部的文件中想使用,只要适当的声明就可以使用;但是全局变量被 static 修饰之后,外部链接属性就变成了内部链接属性,只能在当前所在的源文件内部使用,其他源文件,即使声明,也无法正常使用。
(3)static修饰函数
static 修饰函数和 static 修饰全局变量⼀模⼀样,参照修饰全局变量理解。
3.const(恒定的、不变的)
(1)const修饰变量
#include <stdio.h>
int main()
{
int m = 0;
m = 2;//m是可以修改的
const int a = 0;
a = 2;//a是不能被修改的
return 0;
}
注:
const修饰变量虽然不能直接修改,但是可以通过该变量的地址去间接修改其值,所以是有漏洞可钻的,而const修饰指针完善了这一点。
(2)const修饰指针
void test1()//const在*左边
{
int n = 10;
int m = 20;
const int* p = &n;
*p = 20;//ok? ,不可以
p = &m; //ok? ,可以
}
void test2()//const在*右边
{
int n = 10;
int m = 20;
int *const p = &n;
*p = 20; //ok? ,可以
p = &m; //ok? ,不可以
}
void test3()//*左右两边都有const
{
int n = 10;
int m = 20;
int const * const p = &n;
*p = 20; //ok? ,不可以
p = &m; //ok? ,不可以
}
int main()
{
//测试const放在*的左边情况
test1();
//测试const放在*的右边情况
test2();
//测试*的左右两边都有const
test3();
return 0;
}
结论:
• const如果放在*的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变,但是指针变量本身的内容(地址)可变。
• const如果放在*的右边,修饰的是指针变量本身,保证了指针变量本身的内容(地址)不能修改,但是指针指向的内容,可以通过指针改变。
• const如果在*两边都有,那么指针变量本身的内容(地址)以及指针指向的内容都不能改变。
关于C语言中常见的3种修饰符就介绍到这里,如有疏漏不当之处,欢迎各位大佬斧正。