在写项目 或 阅读别人的代码(一些优秀的源码)中,总能发现一些常见的关键字,随着编程经验的积累大部分还是知道是什么意思
的。
相信很多开发者跟我当初一样,只是基本的常用关键字定义属性会使用,但在关键字概念上及具体的用法「应用场景、优化选择」上却依然有些模糊。
本文为「简书-白开水ln」作者原创;你关注的人,决定了你看到的世界 ^_^.
目录:
关键字 const/static/extern 的「释义和用法」
1、const
2、static
3、extern
4、static与const联合使用
5、extern与const联合使用
6、const与宏的区别?「面试题」期待 & 后续
关键字 const/static/extern 的「释义和用法」
1、const
const
简介:之前常用的字符串常量。const
作用:const
仅仅用来修饰右边的变量(基本数据变量p,指针变量*p)被
const
修饰的(全局)变量是只读的,不能修改。const
基本使用:
- (void)viewDidLoad { [super viewDidLoad]; // 定义变量 int a = 1; // 允许修改值 a = 20; // const两种用法 // const:修饰基本变量p // 这两种写法是一样的,const只修饰右边的基本变量b const int b = 20; // b:只读变量 int const b = 20; // b:只读变量 // 不允许修改值,错误 b = 1; // const:修饰指针变量*p,带*的变量,就是指针变量. // 定义一个指向int类型的指针变量,指向a的地址 int *p = &a; int c = 10; // 允许修改p指向的地址, p = &c; // 允许修改p访问内存空间的值 *p = 20;//--------------------------- 面试题 ------------------------------// // const修饰指针变量访问的内存空间,修饰的是右边*p1, // 两种方式一样 const int *p1; // *p1:只读 p1:变量 int const *p1; // *p1:只读 p1:变量 // const修饰指针变量p1 int * const p1; // *p1:变量 p1:只读 // 第一个const修饰*p1 第二个const修饰 p1 // 两种方式一样 const int * const p1; // *p1:只读 p1:只读 int const * const p1; // *p1:只读 p1:只读} 注意: 判断p 和 *p是只读还是变量,关键是看const在谁前面。
const
开发中应用场景
@implementation ViewController// 定义只读全局常量 => 代替宏NSString * const str = @"123";// 当一个方法的参数,只读.- (void)test:(NSString * const)name { }// 指针只读,不能通过指针修改值- (void)test1:(int const *)a { }// 基本数据类型只读- (void)test2:(int const)a { }@end
2、static
static
简介:可释义为“静态”的意思。static
作用:修饰局部变量:
被
static
修饰局部变量,延长生命周期,跟整个应用程序有关。被
static
修饰局部变量,只会分配一次内存。被
static
修饰局部变量什么分配内存?【程序一运行就会给static修饰变量分配内存】。修饰全局变量:
被
static
修饰全局变量,会作修改用域(防止重复声明全局变量),只能在当前文件下使用。即当前文件内部才能访问该全局变量。static
基本使用:保证局部变量永远只初始化一次,在程序的运行过程中永远只有一份内存, 生命周期类似全局变量了,但是作用域不变。这句话怎么理解呢?还是以代码例子来讲解吧。
// 被`static`修饰局部变量-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { //声明一个局部变量i int i = 0; // 方式一 static int i = 0; // 方式二 i ++; NSLog(@"i=%d",i); } 打印输出: 方法一2016-10-26 14:58:48.290 test[2760:170260] i=12016-10-26 14:58:49.044 test[2760:170260] i=12016-10-26 14:58:49.200 test[2760:170260] i=1方式二2016-10-26 15:07:34.276 test[2817:175155] i=12016-10-26 15:07:35.347 test[2817:175155] i=22016-10-26 15:07:35.761 test[2817:175155] i=3注解 方式一:因为每次点击进入这个方法就会重新初始化一个全新的变量i = 0,加加了一次后值变为1,然后打印出结果为1, 出了这个方法后局部变量i就被释放回收。 方式二:它不是每次进去都被初始化赋值为0了么,怎么能累加呢。 这就是关键字static修饰的局部变量的作用,让局部变量永远只初始化一次,一份内存,生命周期已经跟全局变量类似了,只是作用域不变。
iOS 中在一个文件声明的全局变量,工程的其他文件也是能访问的,但是我又不想让其他文件访问,这时就可以用static
修饰它了,比较典型的是使用GCD
一次性函数创建的单例,全局变量基本上都会用static
修饰。
// 被`static`修饰全局变量@implementation LoginTool// static修饰全局变量,让外界文件无法访问static LoginTool *_sharedManager = nil; + (LoginTool *)sharedManager { static dispatch_once_t oncePredicate; dispatch_once(&oncePredicate, ^{ _sharedManager = [[self alloc] init]; }); return _sharedManager; }
3、extern
extern
简介:可释义为“外部”的意思。extern
作用:只是用来声明外部全局变量,注意extern
只能声明,不能用于定义。extern
工作原理:先在当前文件查找有没有全局变量,没有找到,才会去其他文件查找。extern
基本使用
在 ViewController.m 文件中 定义个全局的常量int i = 15; 在 AppDelegate.m 文件中声明extern int i;NSLog(@"%d",i); // 打印输出 15
4、static与const联合使用
static与const作用:声明一个只读的静态变量
需求:1、变量为只读,防止修改 2、只在当前文件下使用(非全局),可以使用static与const组合。
// iOS中staic和const常用使用场景,是用来代替宏,把一个经常使用的字符串常量,定义成静态全局只读变量.// 开发中经常拿到key修改值,因此用const修饰key,表示key只读,不允许修改。static修饰后表示只能本文件访问。static NSString * const key = @"name";// 如果 const修饰 *key1,表示*key1只读,key1还是能改变。static NSString const *key1 = @"name";
5、extern与const联合使用
开发中使用场景:在 多个文件中 经常使用的同一个字符串常量,可以使用
extern
与const
组合。原因:
使用
extern
与const
组合:在每个文件都需要定义一份静态全局变量(报重复定义错误)。使用
extern
与const
组合:只需要定义一份全局变量,多个文件共享。全局常量正规写法:全局变量不能定义在自己类中,开发中便于管理所有的全局变量,通常搞一个
GlobeConst
文件,里面专门定义全局变量,统一管理,要不然项目文件多不好找。
在开发中,我们通常会单独抽一个类来管理一些全局的变量或常量,下面来看看高逼格的一种做法:
// GlobeConst.m#import "GlobeConst.h"// 定义整个项目中全局变量//--------------------------- 首页 ------------------------------////NSString * const home_name = @"name";//--------------------------- 发现 ------------------------------////NSString * const discover_name = @"name";//--------------------------- 圈子 ------------------------------////NSString * const circle_name = @"name";//--------------------------- 我的 ------------------------------////
// GlobeConst.h#import <Foundation/Foundation.h>#import <UIKit/UIKit.h>// 在开发中,我们通常会单独抽一个类来管理一些全局的变量或常量,下面来看看【高逼格】的一种做法:#ifdef __cplusplus#define LNKIT_EXTERN extern "C" __attribute__((visibility ("default")))#else#define LNKIT_EXTERN extern __attribute__((visibility ("default")))#endif// 声明整个项目中全局变量(把声明放到.h中)//--------------------------- 首页 ------------------------------////extern NSString * const home_name;//--------------------------- 发现 ------------------------------//// 系统UIKIT_EXTERN NSString * const discover_name;//--------------------------- 圈子 ------------------------------//// 高逼格LNKIT_EXTERN NSString * const circle_name;//--------------------------- 我的 ------------------------------////
总结:这样,只要导入头文件,就可以全局的使用定义的变量或常量。
6、const与宏的区别?「面试题」
从四点回答:
编译时刻:宏是预编译(编译之前处理);
const
是编译阶段。编译检查:宏不做检查,不会报编译错误,只是替换;
const
会编译检查,会报编译错误。宏的好处:宏能定义一些函数 或 方法。
const
不能。宏的坏处:使用大量宏,容易造成编译时间久,每次都需要重新替换。
注意:很多
Blog
都说大量使用宏,会消耗大量内存,我这验证并不会生成很多内存,宏定义的是常量,常量都放在常量区,只会生成一份内存。提示:苹果不推荐我们抽成宏,推荐我们使用
const
常量,Swift
已干掉了。代码示例:
// 常见的常量:抽成宏#define LNAccount @"account"#define LNUserDefault [NSUserDefaults standardUserDefaults]// 字符串常量static NSString * const account = @"account"; - (void)viewDidLoad { [super viewDidLoad]; // 偏好设置存储 // 使用宏 [LNUserDefault setValue:@"123" forKey:LNAccount]; // 使用const常量 [[NSUserDefaults standardUserDefaults] setValue:@"123" forKey:account]; }
未完----------。待续
未完----------。待续
未完----------。待续
期待
如果在阅读过程中遇到 error,希望你能 Issues 我,谢谢。
如果你想为【本文相关】分享点什么,也希望你能 Issues 我,我非常想为这篇文章增加更多实用的内容,谢谢。
「博客原文」对本文我会【不定时、持续更新、一些 学习心得与文章、实用才是硬道理】^_^.
About me
【我也是对所花费时间的一个总结】
我只是个【有思想的伐码猿??】加上【自己的学习总结??】写出来的文章。
http://www.cnblogs.com/Plainboiledwater/p/6752443.html