美文网首页
static、const、extern

static、const、extern

作者: QYCD | 来源:发表于2021-03-31 17:54 被阅读0次

生命周期: 一个变量能存活多久,什么时候分配内存,内存什么时候回收
作用域: 一个变量在什么范围内是可见的,可用的

static

分为修饰局部变量和全局变量
在函数或者代码块内声明的变量叫局部变量

修饰局部变量:
  • 在程序中只有一份内存
  • 修改了局部变量的生命周期

局部变量是存储在栈区的,其生命周期是整个代码块,作用域也是整个代码块,出了这个代码块,该变量的内存就会被回收,局部变量也被销毁。

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    NSInteger count = 0;
    count ++;
    NSLog(@"count: %ld", count);
}

多次点击屏幕,打印结果:
[ViewController.m:40行] count: 1
[ViewController.m:40行] count: 1
[ViewController.m:40行] count: 1

局部变量count是声明在touchesBegan:withEvent:方法的代码块内的,其生命周期和作用域均是该代码块。count初始化值为0,每执行一次结束后count就会被销毁,再次执行时 count又会被重新创建和在栈区申请内存

当用static修饰局部变量时,变量被称为静态局部变量,静态局部变量和全局变量、静态全局变量一样存储在全局/静态存储区。存储在全局/静态存储区的变量其生命周期同程序生命周期,也就是直到程序结束它才会销毁。

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    static NSInteger count = 0;
    count ++;
    NSLog(@"count: %ld", count);
}
多次点击屏幕,打印结果:
[ViewController.m:40行] count: 1
[ViewController.m:40行] count: 2
[ViewController.m:40行] count: 3

首次点击屏幕,即执行函数体内代码时,由于static修饰局部变量count,在全局/静态区申请了一块内存,该内存生命周期同整个源程序,则下次执行该函数体内代码时,不会重新申请新的一块内存,而是找到这块叫count的内存,继续上一次结果进行计算。即使pop出当前VC(当前VC销毁),再次进入VC且点击屏幕执行,count的值仍会从之前值累加,因为static修饰了局部变量count,其生命周期同整个程序,不会随着当前VC的销毁而销毁

修饰全局变量
  • 修改了全局变量的作用域,生命周期不会改变
  • 避免重复定义全局变量

全局变量存储在全局/静态存储区,它的生命周期同整个源程序,直到程序结束才销毁,我们可以使用extern关键字来引用这个全局变量。

如下我们可以使用extern关键字访问别的文件定义的全局变量(PS: IDE并不会自动补全)


image.png image.png

运行打印结果:


image.png

如果我们使用static修饰全局变量,则该变量作用域仅限于该文件


const

意为"常量、常数"

const用来修饰右边的基本变量或指针变量,被const修饰的变量是只读的。

如下图,变量a被const修饰,a是只读的,不能被修改


image.png
int const *p; //*p只读 p变量
int * const p; //*p变量 p只读
const int * const p; //p和*p都只读
int const * const p; //p和*p都只读

判断p和p是只读还是变量,关键看const在谁的前面,如果在p前面,那么p是只读,p还是变量,在p前面,那么p只读,p变量。

const常用用法:
定义一个全局只读变量,常和static一起使用,修改了其作用域,只在本文件内访问的只读变量
static NSString *const kLogin = @"/login";

extern

在开发中,我们通常会单独抽一个类来管理一些全局的变量或常量
比如:

.h文件:
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface Define : NSObject

extern NSString * const kLoginNoti;

@end

NS_ASSUME_NONNULL_END

.m文件:
#import "Define.h"

NSString *const kLoginNoti = @"notification.app.login";

@implementation Define

@end

使用时,引入该文件#import "Define.h",则在该文件中即可使用定义的字段

[[NSNotificationCenter defaultCenter] postNotificationName:kLoginNoti object:nil];

const与宏的区别

编译时刻: 宏是预编译(编译之前);const是编译阶段
编译检查: 宏不做检查,不会报编译错误,只是替换;const会编译检查,会报编译错误
宏的好处: 宏能定义函数、方法;const不能
宏的弊端: 如果代码中大量的使用宏会使预编译时间变长

PS: 定义一个字符串的宏,赋值给多个变量,打印其内存地址,经过测试: 宏定义的是常量,常量都放在常量区,只会生成一份内存,故网上说的是不对的

#define SCREEN_Width    ([UIScreen mainScreen].bounds.size.width)
#define SCREEN_Height   ([UIScreen mainScreen].bounds.size.height)

参考:
iOS中static,const,extern相关的问题
IOS 关键字const 、static、extern详解
iOS const、宏、static、extern的关系

相关文章

网友评论

      本文标题:static、const、extern

      本文链接:https://www.haomeiwen.com/subject/eiyhhltx.html