文章目录
前言
笔者本周在学习单例模式时,用到了static关键字,特此总结博客记录学习static,const,extern关键字的过程
一、static
static------静态,我们将用static修饰的变量称为静态变量。
静态变量 的生命周期与程序的运行时间相同,它们在程序启动时被创建,在程序结束时才被销毁 。这与局部变量(在函数内部定义的变量)不同,局部变量的生命周期仅限于函数的执行过程。因此被称为静态变量。
static分两种情况,修饰局部变量和全局变量。
我们首先要搞清楚生命周期和作用域的概念。
- 生命周期:这个变量能存活多久,它所占用的内存什么时候分配,什么时候收回。
- 作用域:说白了就是这个变量在什么区域是可见的,可以拿来用的。
static修饰局部变量
在函数或者说代码块内部声明的变量叫局部变量。
我们一段代码来展开我们的讲解:
objectivec
- (int)add {
int a = 0;
a++;
return a;
}
- (void)viewDidLoad {
[super viewDidLoad];
for (int i = 0; i < 5; i++) {
NSLog(@"%d", [self add]);
}
}
在add代码块中,a就是一个局部变量,当我们重复调用add方法时,我们的变量a也在被程序不断地分配空间与销毁。当一次add方法结束后,也就是我们的变量超出作用域时,我们的a就会被销毁,下一次调用变量a时系统会为其重新分配内存空间。
而从底层的角度来理解,就是大多数局部变量存储在栈内存中,这意味着它们的内存分配和释放是自动处理的。当局部变量超出其作用域时,栈上的内存会自动回收。
打印结果:
可以看到我们的a是在不断被重置的
当我们用static修饰局部变量时,变量被称为静态局部变量,这个静态局部变量和全局变量,静态全局变量一样,是存储在静态存储区。由于存储在静态存储区,所以这块内存直到程序结束才会销毁。
也就是说,静态局部变量的生命周期 是整个源程序 。但是它只在声明它的代码块可见,也就是说它的作用域是声明它的代码块。
我们把局部变量a用static修饰:
objectivec
- (int)add {
static int a = 0;
a++;
return a;
}
- (void)viewDidLoad {
[super viewDidLoad];
for (int i = 0; i < 5; i++) {
NSLog(@"%d", [self add]);
}
}
打印结果:
可以看到我们重复调用add方法时我们的变量a并没有被销毁,这是因为a作为静态局部变量:
- 存储在静态内存区:静态局部变量通常存储在程序的静态内存区域,而不是栈内存中。栈内存中的变量在函数调用结束时会自动销毁,但静态内存区中的变量在程序运行期间一直存在 ,也就是说其作用域是整个源程序。
- 初始化只发生一次:静态局部变量的初始化仅在第一次进入包含它的作用域时发生。一旦被初始化,它的值会一直保持不变,不会在后续函数调用中重新初始化。这是因为在函数的每次调用之间,静态局部变量的状态会得到保持,因此它们的值会被保留。
总之,静态局部变量之所以不会被销毁,是因为它们在内存中只有一个实例,其生命周期跨越了函数调用,而不仅仅局限于函数内部。这使得它们非常适合用于需要保持状态或跟踪信息的情况。
static修饰全局变量
当全局变量没有使用static修饰符时,其存储在静态存储区,直到程序结束才销毁。也就是其作用域是整个源程序。我们可以使用extern关键字来引用这个全局变量。
我们可以在viewcontroller文件中直接调用全局变量b
当我们用static修饰b时
出现如下错误:
其实就是在其他文件中我们无法访问到变量b了
总结
static修饰局部变量:将局部变量的本来分配在栈区改为分配在静态存储区,改变了局部变量的生命周期与作用域。
static修饰全局变量:本来是在整个源程序的所有文件都可见,static修饰后,改为只在申明自己的文件可见,即修改了作用域。
二、const
const主要强调当前变量无法被修改
这段代码表明我们的c无法被修改
这样定义相对于用#define来定义的话,优点就在于它指定了变量的类型,而#define是不能指定变量的类型的。
三、extern
extern 是一个关键字,用于声明在其他源文件中定义的全局变量或函数。它的作用是告诉编译器某个标识符的定义在其他文件中,并且在当前文件中要使用它 。extern 主要用于跨文件之间共享变量和函数的声明。
声明全局变量
extern 用于声明全局变量,表示该变量的定义在其他源文件中。这允许多个源文件共享同一个全局变量。
objectivec
// 在文件1.h中定义全局变量
int globalVariable;
// 在文件2.c中使用全局变量的声明
extern int globalVariable;
int main() {
globalVariable = 42;
return 0;
printf("%d", globalVariable);
}
输出结果:
声明函数
extern 也可用于声明函数,表示该函数的定义在其他源文件中。这允许在一个源文件中调用在另一个源文件中定义的函数。
objectivec
// 在文件1.c中定义函数
void myFunction();
// 在文件2.c中使用函数的声明
extern void myFunction();
int main() {
myFunction(); // 调用在其他文件中定义的函数
return 0;
}
在头文件中使用
通常,extern 声明会放在头文件中,并在需要的源文件中包含该头文件,以便多个源文件可以共享相同的声明。
objectivec
// Header.h 头文件
extern int globalVariable;
extern void myFunction();
objectivec
// 文件1.c
#include "Header.h"
// 使用 globalVariable 和 myFunction
objectivec
// 文件2.c
#include "Header.h"
// 使用 globalVariable 和 myFunction
总结
extern 关键字用于声明在其他源文件中定义的全局变量和函数。它使得不同源文件可以共享全局标识符的声明,从而实现了跨文件的变量和函数的共享和使用。