iOS const、static、extern实操

去阿里面试被问到了好多基本功和底层知识,由于没有总结过,导致有很多用过的东西并不知道怎么表达,遭到了无情的鄙视;决定总结一些知识点,激励自己一下!
先从最基本的写起:先写几个修饰关键字 const、static、extern.

一、const:: 被const修饰的变量是只读的(变量->只读变量).

先从最基础的开始
定义变量

 int a = 1;
 a = 20;// 允许修改值

然后开始进入const
const两种用法
1、const:修饰基本变量p

const int b = 20; // b:只读变量
int const b = 20; // b:只读变量
b = 1; // 会报错// 不允许修改值

2、const:修饰指针类型*p
定义一个指向int类型的指针,指向a的地址

int a = 20;
int *p = &a;
NSLog(@"p == %p---&a == %p",p,&a);
int c = 10;
p = &c;
NSLog(@"p == %p---*p == %d",p,*p);
int d = 11;
*p = d;
NSLog(@"p == %p---*p == %d",p,*p);
//打印结果
2019-07-11 09:45:32.867368+0800 Runtime理解[44662:1691119] p == 0x7ffeefb433ac---*p == 20
2019-07-11 09:45:32.867518+0800 Runtime理解[44662:1691119] p == 0x7ffeefb4339c---*p == 10
// 允许修改p指向的地址
2019-07-11 09:45:32.867637+0800 Runtime理解[44662:1691119] p == 0x7ffeefb4339c---*p == 11
// 允许修改p访问内存空间的值

const修饰指针变量访问的内存空间,修饰的是右边*p1,

int a = 20;
const int *p = &a; 
NSLog(@"p == %p---*p == %d",p,*p);
int c =10;
p = &c;
NSLog(@"p == %p---*p == %d",p,*p);
//打印结果
2019-07-11 10:15:54.968002+0800 Runtime理解[45151:1709783] p == 0x7ffee3f193ac---*p == 20
2019-07-11 10:15:54.968132+0800 Runtime理解[45151:1709783] p == 0x7ffee3f1939c---*p == 10
// 允许修改p指向的地址

 int d = 11;
*p = d;//报错,Read-only variable is not assignable(只读变量不可赋值)
// 不允许修改p访问内存空间的值

int a = 20;
const *p = &a; 
NSLog(@"p == %p---*p == %d",p,*p);
int c =10;
p = &c;
NSLog(@"p == %p---*p == %d",p,*p);
//打印结果
2019-07-11 10:15:54.968002+0800 Runtime理解[45151:1709783] p == 0x7ffee3f193ac---*p == 20
2019-07-11 10:15:54.968132+0800 Runtime理解[45151:1709783] p == 0x7ffee3f1939c---*p == 10
// 允许修改p指向的地址

 int d = 11;
*p = d;//报错,Read-only variable is not assignable(只读变量不可赋值)
// 不允许修改p访问内存空间的值
int a = 20;
int const *p = &a; 
NSLog(@"p == %p---*p == %d",p,*p);
int c =10;
p = &c;
NSLog(@"p == %p---*p == %d",p,*p);
//打印结果
2019-07-11 10:15:54.968002+0800 Runtime理解[45151:1709783] p == 0x7ffee3f193ac---*p == 20
2019-07-11 10:15:54.968132+0800 Runtime理解[45151:1709783] p == 0x7ffee3f1939c---*p == 10
// 允许修改p指向的地址

 int d = 11;
*p = d;//报错,Read-only variable is not assignable(只读变量不可赋值)
// 不允许修改p访问内存空间的值
总结:const int *p 作用等同于 int const *p 
*p 是常量 p是变量
int a = 20;
int * const p = &a; 
NSLog(@"p == %p---*p == %d",p,*p);
int c =10;
p = &c; //报错,Read-only variable is not assignable(只读变量不可赋值)
// 不允许修改p指向的地址
int d = 11;
*p = d;
NSLog(@"p == %p---*p == %d",p,*p);
// 打印结果
2019-07-11 10:50:44.694506+0800 Runtime理解[45665:1731013] p == 0x7ffee8f413ac---*p == 20
2019-07-11 10:50:44.694684+0800 Runtime理解[45665:1731013] p == 0x7ffee8f413ac---*p == 11
// 允许修改p访问内存空间的值

总结: int *const p    *p是变量 p是常量;
通过以上代码总结:const修饰的紧右边的为常量,在此就不一一验证,有兴趣的可以自己写代码验证一下;
const int *p              // *p:常量   p:变量
int const *p              // *p:常量   p:变量
int *const p              // *p:变量   p:常量
const int * const p       // *p:常量   p:常量
int const * const p       // *p:常量   p:常量

下面来试验一下const最常用的方法:修饰NSString,废话少说,上代码:

NSString * const str1=@"sdh";
str1 = @"123" //报错
//因为NSString是不可变字符串:指针指向内存的内容是不允许改变的,因为const修饰的是指针 str1:指针不允许指向其他内存;
//所以不可以修改指针指向的原内存中的内容,指针不可以指向其他的内存


 NSString const *str2 = @"sdh";
 str2 = @"123"; //不报错
//因为NSString是不可变字符串:指针指向内存的内容是不允许改变的,因为const修饰的是指针 *str2:指针指向内存的内容不允许改变,所以 *str2 是常量 但str2是变量指针可以指向一天内存;
//所以不可以修改指针指向的原内存中的内容,指针可以指向其他的内存


NSMutableString *const var1 =[NSMutableString string];
NSMutableString *var2 = [NSMutableString stringWithFormat:@"%@",@"123"];
var1 = var2; //报错 因为const修饰的是指针 var1:指针不允许指向其他内存;
[var1  appendString:@"123"]; //不报错 因为NSMutableString是可变字符串:指针指向内存的内容是允许改变的
//所以可以修改指针指向的原内存中的内容,指针不可以指向其他的内存

NSMutableString const *var3 =[NSMutableString string];
var3 = var2; //不报错  因为const修饰的是指针 *var3 所以var3是变量,指针可以指向其他内存地址
[var3 appendString:@"123456"]; //不报错 因为var3是可变字符串指针指向的原内存中的内容可以改变
//所以可以修改指针指向的原内存中的内容,常量指针可以指向其他的内存
NSLog(@"str1 = %@ -- str2 = %@ -- var1 = %@ -- var2 = %@",str1,str2,var1,var2);
//打印结果
2019-07-11 11:28:43.957979+0800 Runtime理解[46292:1755776] str1 = sdh -- str2 = 123 -- var1 = 123 -- var2 = sdh123456

const修饰字符串总结:

NSString *const str1
不可以修改指针指向的原内存中的内容,指针不可以指向其他的内存
NSString const *str2
不可以修改指针指向的原内存中的内容,指针可以指向其他的内存
NSMutableString const *var1
可以修改指针指向的原内存中的内容,指针可以指向其他的内存
NSMutableString *const var2
可以修改指针指向的原内存中的内容,指针不可以指向其他的内存

const用法总结道这里。

二、static和extern简单使用
"static作用":
1、修饰局部变量:
1)延长局部变量的生命周期,程序结束才会销毁。
2)局部变量只会生成一份内存,只会初始化一次。
3)Static关键字不可以改变局部变量的作用域。

@implementation Person
-(instancetype)init{
    self = [super init];
    if (self) {
        [self conlogAge];
        [self conlogAge];
    }
    return self;
}

-(void)conlogAge{
    static NSInteger age = 18;
    age ++;
    NSLog(@"%ld",age);
}


#import "Person.h"
@interface ConstStaticViewController ()
@end
@implementation ConstStaticViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    Person *per = [Person new];
    Person *per2 = [Person new];
}
//打印输出
//2019-07-11 15:19:25.617612+0800 Runtime理解[49598:1888382] 19
//2019-07-11 15:19:25.617712+0800 Runtime理解[49598:1888382] 20
//2019-07-11 15:19:25.617800+0800 Runtime理解[49598:1888382] 21
//2019-07-11 15:19:25.617892+0800 Runtime理解[49598:1888382] 22

注意:ConstStaticViewController是二级页面,我们返回到一级页面,该页面销毁,在重新创建改页面,viewDidLoad会重新执行一次,我们在看打印数据:

2019-07-11 15:42:11.181260+0800 Runtime理解[50022:1905671] 19
2019-07-11 15:42:11.181433+0800 Runtime理解[50022:1905671] 20
2019-07-11 15:42:11.181541+0800 Runtime理解[50022:1905671] 21
2019-07-11 15:42:11.181711+0800 Runtime理解[50022:1905671] 22
2019-07-11 15:42:14.761006+0800 Runtime理解[50022:1905671] 23
2019-07-11 15:42:14.761159+0800 Runtime理解[50022:1905671] 24
2019-07-11 15:42:14.761285+0800 Runtime理解[50022:1905671] 25
2019-07-11 15:42:14.761378+0800 Runtime理解[50022:1905671] 26

说明:
1、age这个变量并未因持有他的对象的销毁儿销毁,局部变量的生命周期被延长
2、而且, [self conlogAge]函数被调用多次,age这个变量并未重新初始化,而是跳过初始化,继续进行 ++操作,所以:局部变量只会生成一份内存,只会初始化一次。


-(void)conlogAge{
    static NSInteger age = 18;
    age ++;
    NSLog(@"%ld",age);
}
-(void)showAge{
    age++;//直接报错
    extern NSInteger age; //编译时报错
    NSLog(@"%ld",age);
}

3、被static修饰过的变量,在其他作用域是不能访问的。

2、static修饰全局变量

1)只能在本文件中访问,修改全局变量的作用域,生命周期不会改
2)避免重复定义全局变量

NSString *allChange = @"allChange";//全局变量,本文件直接用,其他文件借助extern调用
static NSString *changes =@"change";//全局变量,本文件直接用,其他文件借助不能调用,用extern调用,会报错

三、const、static配合使用
开发时常用的写法,用const、和static配合使用来代替宏的部分功能(#define)
一、const与宏的区别(面试题):

  • "const简介":之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽成宏,推荐我们使用const常量。
  • "执行时刻":宏是预编译(编译之前处理),const是编译阶段。
  • "编译检查":宏不做检查,不会报编译错误,只是替换,const会编译检查,会报编译错误。
  • "宏的好处":宏能定义一些函数,方法。 const不能。
  • "宏的坏处":使用大量宏,容易造成预编译时间久。
#define CHANGE @"change";
static NSString *const changes =@"change";

虽然测试过,及时用相当数量的宏编译时间并不会差很多,但是,我们还是要按照苹果的推荐来的好,用第二个表示方法。

四、extern使用
"extern作用":只是用来获取全局变量(包括全局静态变量)的值,不能用于定义变量。
"extern工作原理":先在当前文件查找有没有全局变量,没有找到,才会去其他文件查找。
废话补多说:代码解释

#import "SLStaticDemo.h"
NSInteger age = 10;
@implementation SLStaticDemo
@end
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor whiteColor];
    
    extern NSInteger age;
    NSLog(@"age = %ld", (long)age);
    
    age += 10;
    NSLog(@"age = %ld", (long)age);
}
@end

打印结果:

image

从输出结果 age = 10 我们可以看到即便我们在ViewController.m中并没有import SLStaticDemo.h也能得到SLStaticDemo中定义的age变量,这就是extern关键字的功劳(extern可以访问全局变量);
注:这里理解起来很简单,懒得自己写了,参照的大神的代码,网址:https://www.jianshu.com/p/9c09989b6862

好,用了将近一天的时间,把这三个基本的关键字理清了,可能有写啰嗦,希望大家选择性参考。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容