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

文章目录


前言

笔者本周在学习单例模式时,用到了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 关键字用于声明在其他源文件中定义的全局变量和函数。它使得不同源文件可以共享全局标识符的声明,从而实现了跨文件的变量和函数的共享和使用。

相关推荐
Magnetic_h13 小时前
【iOS】单例模式
笔记·学习·ui·ios·单例模式·objective-c
归辞...15 小时前
「iOS」——单例模式
ios·单例模式·cocoa
yanling202316 小时前
黑神话悟空mac可以玩吗
macos·ios·crossove·crossove24
归辞...18 小时前
「iOS」viewController的生命周期
ios·cocoa·xcode
crasowas1 天前
Flutter问题记录 - 适配Xcode 16和iOS 18
flutter·ios·xcode
2401_852403551 天前
Mac导入iPhone的照片怎么删除?快速方法讲解
macos·ios·iphone
SchneeDuan1 天前
iOS六大设计原则&&设计模式
ios·设计模式·cocoa·设计原则
JohnsonXin2 天前
【兼容性记录】video标签在 IOS 和 安卓中的问题
android·前端·css·ios·h5·兼容性
蒙娜丽宁2 天前
Go语言错误处理详解
ios·golang·go·xcode·go1.19
名字不要太长 像我这样就好2 天前
【iOS】push和pop、present和dismiss
学习·macos·ios·objective-c·cocoa