【iOS】浅析static,const,extern关键字

文章目录

  • 前言
  • 一、static
    • static修饰局部变量
    • static修饰全局变量
    • 总结
  • 二、const
  • 三、extern
    • 声明全局变量
    • 声明函数
    • 在头文件中使用
    • 总结


前言

笔者本周在学习单例模式时,用到了static关键字,特此总结博客记录学习static,const,extern关键字的过程

一、static

static——静态,我们将用static修饰的变量称为静态变量。

静态变量的生命周期与程序的运行时间相同,它们在程序启动时被创建,在程序结束时才被销毁。这与局部变量(在函数内部定义的变量)不同,局部变量的生命周期仅限于函数的执行过程。因此被称为静态变量

static分两种情况,修饰局部变量和全局变量。
我们首先要搞清楚生命周期和作用域的概念。

  • 生命周期:这个变量能存活多久,它所占用的内存什么时候分配,什么时候收回。
  • 作用域:说白了就是这个变量在什么区域是可见的,可以拿来用的。

static修饰局部变量

在函数或者说代码块内部声明的变量叫局部变量。

我们一段代码来展开我们的讲解:

- (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时系统会为其重新分配内存空间。

而从底层的角度来理解,就是大多数局部变量存储在栈内存中,这意味着它们的内存分配和释放是自动处理的。当局部变量超出其作用域时,栈上的内存会自动回收。

打印结果:
【iOS】浅析static,const,extern关键字_第1张图片
可以看到我们的a是在不断被重置的


当我们用static修饰局部变量时,变量被称为静态局部变量,这个静态局部变量和全局变量,静态全局变量一样,是存储在静态存储区。由于存储在静态存储区,所以这块内存直到程序结束才会销毁

也就是说,静态局部变量的生命周期整个源程序。但是它只在声明它的代码块可见,也就是说它的作用域是声明它的代码块

我们把局部变量a用static修饰:

 - (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时
在这里插入图片描述
出现如下错误:
【iOS】浅析static,const,extern关键字_第2张图片
其实就是在其他文件中我们无法访问到变量b了

总结

static修饰局部变量:将局部变量的本来分配在栈区改为分配在静态存储区,改变了局部变量的生命周期与作用域
static修饰全局变量:本来是在整个源程序的所有文件都可见,static修饰后,改为只在申明自己的文件可见,即修改了作用域


二、const

const主要强调当前变量无法被修改
在这里插入图片描述

这段代码表明我们的c无法被修改

这样定义相对于用#define来定义的话,优点就在于它指定了变量的类型,而#define是不能指定变量的类型的。


三、extern

extern 是一个关键字,用于声明在其他源文件中定义的全局变量或函数它的作用是告诉编译器某个标识符的定义在其他文件中,并且在当前文件中要使用它。extern 主要用于跨文件之间共享变量和函数的声明

声明全局变量

extern 用于声明全局变量,表示该变量的定义在其他源文件中。这允许多个源文件共享同一个全局变量。

// 在文件1.h中定义全局变量
int globalVariable;

// 在文件2.c中使用全局变量的声明
extern int globalVariable;

int main() {
    globalVariable = 42;
    return 0;
	printf("%d", globalVariable);
}

输出结果:
在这里插入图片描述

声明函数

extern 也可用于声明函数,表示该函数的定义在其他源文件中。这允许在一个源文件中调用在另一个源文件中定义的函数。

// 在文件1.c中定义函数
void myFunction();

// 在文件2.c中使用函数的声明
extern void myFunction();

int main() {
    myFunction(); // 调用在其他文件中定义的函数
    return 0;
}

在头文件中使用

通常,extern 声明会放在头文件中,并在需要的源文件中包含该头文件,以便多个源文件可以共享相同的声明。

// Header.h 头文件
extern int globalVariable;
extern void myFunction();
// 文件1.c
#include "Header.h"
// 使用 globalVariable 和 myFunction
// 文件2.c
#include "Header.h"
// 使用 globalVariable 和 myFunction

总结

extern 关键字用于声明在其他源文件中定义的全局变量和函数。它使得不同源文件可以共享全局标识符的声明,从而实现了跨文件的变量和函数的共享和使用。

你可能感兴趣的:(ios)