【iOS】static、const、extern关键字

static、const、extern关键字

)

前言

属性关键字博客,这里补充static、const、extern关键字的学习。

static

static既可以修饰局部变量,也可以修饰全局变量。用static修饰的变量我们称为静态变量。

静态变量:生命周期与程序运行时间相同,只初始化一次,在程序启动时创建,在程序结束时销毁。

修饰局部变量

称为静态局部变量。

对比一下下面两个代码:

objc 复制代码
-(int)add {
    int a = 0;
    a++;
    return a;
}
- (void)viewDidLoad {
    [super viewDidLoad];
    for (int i = 0; i < 5; i++) {
        NSLog(@"%d", [self add]);
    }
}
objc 复制代码
-(int)add {
    static int a = 0;
    a++;
    return a;
}
- (void)viewDidLoad {
    [super viewDidLoad];
    for (int i = 0; i < 5; i++) {
        NSLog(@"%d", [self add]);
    }
}
  • 代码一:a作为局部变量

在add代码块中,a作为一个局部变量,当我们重复调用add方法时,局部变量a也在不断地被分配空间初始化与销毁。当一次add方法结束后,即变量超出作用域时,a被销毁,下一次调用时又重新分配内存空间。

也就是说它的生命周期是函数调用时开始,函数结束后销毁。

底层逻辑实际上是调用add方法时,系统在栈区上分配一块内存,然后a = 0存入该内存,每次执行函数时,都是在栈上对a进行操作,当add方法返回时,栈被销毁,再次调用时,系统重新为a分配一次栈内存

  • 代码二:a作为静态局部变量

当使用static修饰局部变量时,变量被称为静态局部变量。与全局变量、静态全局变量一样,静态局部变量也是存储在静态存储区的。由于存储在静态存储区,因此这里的内存会直到程序结束才销毁。

也就是说它的生命周期是程序开始时分配,程序结束时销毁。

这里我们重点总结一下静态局部变量的特点:

  • 存储在静态内存区:静态局部变量与局部变量不同,它不存储在栈内存中,而是静态内存区域。静态内存区中的变量在程序运行期间一直存在。
  • 初始化只发生一次:静态局部变量的初始化仅在第一次进入它的作用域时发生。一旦被初始化,在函数的每次调用时,静态局部变量的状态都会得到保持,它们的值会被保留,一直保持不变,不会在后续函数调用中重新初始化。

修饰全局变量

称为静态全局变量。

下面我们通过代码对比一下有没有static修饰全局变量的区别:

  • 没有static修饰符

定义一个全局变量b,存储区在静态存储区,直到程序结束才销毁。

objc 复制代码
#import "AViewController.h"
#import "BViewController.h"

@interface AViewController ()

@end

@implementation AViewController

int b = 10;

在别的界面想调用它时,使用extern关键字来引用这个全局变量。

objc 复制代码
#import "BViewController.h"

@interface BViewController ()

@end

@implementation BViewController

extern int b;

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor greenColor];
    NSLog(@"%d", b);
}
  • 有static修饰符
objc 复制代码
@interface AViewController ()

@end

@implementation AViewController

static int b = 10;

这时我们想在别的地方调用b这个全局变量时,会出现报错:

这说明这时我们已经不能在其它文件中访问到这个全局变量b了。

总结

  • static修饰局部变量时,将分配在栈区改为分配在静态存储区,改变了局部变量的生命周期。
  • static修饰全局变量时,将源程序所有文件可见改为只在申明自己的文件可见,改变了作用域。

const

const主要强调当前变量无法被修改

objc 复制代码
const int c = 1;
c = 2;

这样就会出现提示我们c无法被修改的错误:

这样相当于用#define来定义,但const可以指定变量的类型,#define不能。

objc 复制代码
#define c 1

extern

extern主要是跨文件之间的变量共享和函数声明,也就是用于声明在其它源文件中定义的全局变量或函数。它用来告诉编译器某个标识符的定义在其它文件中,但在当前文件中要使用它。

声明全局变量

这个使用的demo已经在上面展示。

声明函数

表示函数定义在其它源文件,但允许在该源文件中调用定义的函数。

objc 复制代码
void test(void) {
    NSLog(@"Hello iOS");
}
objc 复制代码
extern void test(void);

- (void)viewDidLoad {
    [super viewDidLoad];
    test();
}

还有一种写法:

extern声明一般写在头文件中,因此可以在需要的源文件中包含该头文件,以便多个源文件可以共享相同的声明。

objc 复制代码
#ifndef Header_h
#define Header_h
extern int b;

#endif /* Header_h */
objc 复制代码
#import "BViewController.h"
#import "Header.h"

@interface BViewController ()

@end

@implementation BViewController
- (void)viewDidLoad {
  [super viewDidLoad];
  NSLog(@"%d", b);
}

总结

extern关键字使得不同文件可以共享相同的变量和函数,实现跨文件的共享和使用。

相关推荐
未来侦察班4 小时前
一晃13年过去了,苹果的Airdrop依然很坚挺。
macos·ios·苹果vision pro
锐意无限9 小时前
Swift 扩展归纳--- UIView
开发语言·ios·swift
符哥20089 小时前
用Apollo + RxSwift + RxCocoa搭建一套网络请求框架
网络·ios·rxswift
文件夹__iOS14 小时前
AsyncStream 进阶实战:SwiftUI 全局消息流极简实现
ios·swiftui·swift
2501_9160088916 小时前
深入解析iOS机审4.3原理与混淆实战方法
android·java·开发语言·ios·小程序·uni-app·iphone
忆江南16 小时前
Flutter深度全解析
ios
山水域16 小时前
Swift 6 严格并发检查:@Sendable 与 Actor 隔离的深度解析
ios
楚轩努力变强17 小时前
iOS 自动化环境配置指南 (Appium + WebDriverAgent)
javascript·学习·macos·ios·appium·自动化
游戏开发爱好者82 天前
日常开发与测试的 App 测试方法、查看设备状态、实时日志、应用数据
android·ios·小程序·https·uni-app·iphone·webview
黑码哥2 天前
ViewHolder设计模式深度剖析:iOS开发者掌握Android列表性能优化的实战指南
android·ios·性能优化·跨平台开发·viewholder