博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS const static extern 汇总
阅读量:2092 次
发布时间:2019-04-29

本文共 9410 字,大约阅读时间需要 31 分钟。

关键字const/static/extern的释义和用法  1、const 这个单词翻译成中文是“常量”的意思。在程序中我们知道“常量”的值是不能变的,固定的。所以const关键字的作用就呼之欲出了: (1) const用来修饰右边的基本变量或指针变量(2) 被修饰的变量只读,不能被修改 下面举个最简单的例子: //声明一个int类型的变量a,变量初始化值为10,并且变量a左边有一个const关键字修饰int  const  a = 10;//因为变量a被const修饰,就成为了只读,不能被修改赋值了,所以下面这行代码是错误的a = 20;//错误代码//上面第一句代码和这句代码是等价的,都是修饰变量a让其只读const  int   a = 10; 下面再看一组练习,这组练习完成后,相信你就完全理解const的用法: 分别指出下面四行代码中 *p 和p是只读还是变量 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的常用用法: //定义一个全局只读变量NSString  * const Kname = @"appkey";//static修饰后此全局变量只能本文件访问static NSString *const Key = @"hddjj”;  2、static 这个单词翻译成中文是“静态”的意思。关从字面上理解还真没法跟他的作用关联起来,下面我们直接先看他的作用: (1)修饰局部变量 保证局部变量永远只初始化一次,在程序的运行过程中永远只有一份内存,  生命周期类似全局变量了,但是作用域不变。这句话怎么理解呢?还是以代码例子来讲解吧。 随便建一个工程,在一个控制器类上监听控制器view的点击事件方法: -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{    //声明一个局部变量i    int i = 0;    //每次点击view来到这个方法时让i自增    i ++;    //打印结果    NSLog(@"i=%d",i);} 输出日志如下: 2016-10-26 14:58:48.290 fff[2760:170260] i=12016-10-26 14:58:49.044 fff[2760:170260] i=12016-10-26 14:58:49.200 fff[2760:170260] i=1.... 从输出日志中我们可以看到i一直等于1,这也是预料之中的,因为每次点击进入这个方法就会重新初始化一个全新的变量i = 0,加加了一次后值变为1,然后打印出结果为1,出了这个方法后局部变量i就被释放回收。所以每次打印出来的结果都为1。 但是我们再看看局部变量i被关键字static修饰后的情况: -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{    //声明一个局部变量i  static  int i = 0;    //每次点击view来到这个方法时让i自增    i ++;    //打印结果    NSLog(@"i=%d",i);} 输出日志如下: 2016-10-26 15:07:34.276 fff[2817:175155] i=12016-10-26 15:07:35.347 fff[2817:175155] i=22016-10-26 15:07:35.761 fff[2817:175155] i=32016-10-26 15:07:36.057 fff[2817:175155] i=42016-10-26 15:07:36.415 fff[2817:175155] i=5.... 上面日志中可以看到i的值一直在自增。什么,它不是每次进去都被初始化赋值为0了么,怎么能累加呢。这就是关键字static修饰的局部变量的作用,让局部变量永远只初始化一次,一份内存,生命周期已经跟全局变量类似了,只是作用域不变。 (2)修饰全局变量 使全局变量的作用域仅限于当前文件内部,即当前文件内部才能访问该全局变量。 iOS中在一个文件声明的全局变量,工程的其他文件也是能访问的,但是我又不想让其他文件访问,这时就可以用static修饰它了,比较典型的是使用GCD一次性函数创建的单例,全局变量基本上都会用static修饰。 下面是一个GCD一次函数创建的单利 @implementation LoginTool//static修饰全局变量,让外界文件无法访问static LoginTool *_sharedManager = nil;+ (LoginTool *)sharedManager {      static dispatch_once_t oncePredicate;      dispatch_once(&oncePredicate, ^{        _sharedManager = [[self alloc] init];    });      return _sharedManager;} (3)修饰函数 static修饰函数时,被修饰的函数被称为静态函数,使得外部文件无法访问这个函数,仅本文件可以访问。这个在oc语言开发中几乎很少用,c语言倒是能看到一些影子,所以不详细探讨。  3、extern 这个单词翻译过来是“外面的、外部的”。顾名思义,它的作用是声明外部全局变量。这里需要特别注意extern只能声明,不能用于实现。 在开发中,我们通常会单独抽一个类来管理一些全局的变量或常量,下面来看看逼格比较高的一种做法: 我们可以在.h文件中extern声明一些全局的常量 //声明一些全局常量extern NSString * const name;extern NSInteger const count; 然后在.m文件中去实现 #import //实现NSString * const name = @"王五";NSInteger const count = 3; 这样,只要导入头文件,就可以全局的使用定义的变量或常量。
extern可置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量或者函数时时,在其他模块中寻找其定义。
(1)extern修饰的全局变量默认是有外部链接的,作用域是整个工程,在一个文件内定义的全局变量,在另一个文件中,通过external全局变量的声明,就可以使用全局变量。 (2)static修饰的全局静态变量,作用域是声明此变量所在的文件。  
extern
首先看代码示例:
GDGPerson.m 文件
#import "GDGPerson.h"@implementation GDGPerson int age = 10;@end
main.m文件 ,不用包含GDGPerson类的头文件
#import
int main(int argc, const char * argv[]) { @autoreleasepool { extern int age; age = 30; NSLog(@" %d", age); } return 0;}
在工程中新添加一个GDGPerson的类
在GDGPerson.m里写 int a = 10; ,在main.m里写 int a ;,NSLog(@"%d",a);打印会报错
因为无法引用外部变量
int a;前加上extern,就可以打印出来,a的值是10
只要你在全局变量前加extern,你的这个文件就可以访问这个全局变量
首先清楚一点,默认条件下,全局变量的是整个程序都能访问的
记住! extern int a; 是并没有分配内存的,这样写不是定义变量
怎么写是定义变量?
int a; 这样写才是定义变量。
在main.m里怎么修改a 的值才不会报错?
这样写 a = 30;
打印出来的值a 是30
所以记住
任何情况下全局变量都是不安全的!为什么? 随时可能会被别人改掉。
总结:
<1>要想访问全局变量可以在前面加extern
<2>extern修饰的变量没有真正内存
static
1.修饰全局变量
GDGPerson.m文件
#import "GDGPerson.h"@implementation GDGPerson static int age = 10;@end
main.m文件 不用包含GDGPerson类的头文件
#import
int main(int argc, const char * argv[]) { @autoreleasepool { extern int age; NSLog(@" %d", age); } return 0;}
那么我想我定义的全局变量只允许本文件访问,其他文件不能访问,怎么办?
简单,在int a = 10; 前加static
只要在全局变量前加static,那么这个全局变量的作用域就会缩小到当前文件,外界就不能访问了。
这时请在GDGPerson.m文件 int a = 10; 前加static,再运行程序,就会发现报错了
好处:保证全局变量安全,外界不可访问与修改
总结:static修饰全局变量,全局变量的作用域仅限于当前文件
2.修饰局部变量的作用
先看代码示例:
main.m文件
void test(){ static int a = 0; a++; NSLog(@"a = %d", a);}int main(int argc, const char * argv[]) { @autoreleasepool { for (int i = 0; i<3; i++) { test(); } } return 0;}
修饰局部变量时,作用域仅限于test函数的大括号,其他地方都不顶用
test这个函数中如果不加static,那么a打印出来的结果永远是1
因为每当调用一次函数,就会定义一个新的变量
每次a的值都是零,加加后就是1
但是加上static后,含义就不一样了
再打印的结果就是1,2,3
因为被static修饰的变量只会初始化一次,永远都只有一份内存
所以当第一次调用test函数时
a有一个内存空间,并且值是0
第二次再调用test函数时由于int a被 static 修饰
所以不会再初始化新值
它会拿到之前的那份内存加加,就会变为1
以此类推,之后就会变为2,3
好处:保住所修饰变量的命,保证它不会挂 
总结:
<1>让局部变量只初始化一次
<2>局部变量在程序中只有一份内存
<3>并不会改变局部变量的作用域,仅仅是改变了局部变量的生命周期(只到程序结束,这个局部变量才会销毁)
const、static、extern简介
一、const与宏的区别(面试题):
* "const简介":之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽成宏,推荐我们使用const常量。
* "执行时刻":宏是预编译(编译之前处理),const是编译阶段。
* "编译检查":宏不做检查,不会报编译错误,只是替换,const会编译检查,会报编译错误。
* "宏的好处":宏能定义一些函数,方法。 const不能。
* "宏的坏处":使用大量宏,容易造成编译时间久,每次都需要重新替换。
注意:很多Blog都说使用宏,会消耗很多内存,我这验证并不会生成很多内存,宏定义的是常量,常量都放在常量区,只会生成一份内存。
图片:
// 常见的常量:抽成宏#define XMGAccount @"account"#define XMGUserDefault [NSUserDefaults standardUserDefaults]// 字符串常量static NSString * const account = @"account";- (void)viewDidLoad { [super viewDidLoad]; // 偏好设置存储 // 使用宏 [XMGUserDefault setValue:@"123" forKey:XMGAccount]; // 使用const常量 [[NSUserDefaults standardUserDefaults] setValue:@"123" forKey:account]; } 二、const作用:限制类型 * 1.const仅仅用来修饰右边的变量(基本数据变量p,指针变量*p) * 2.被const修饰的变量是只读的。 *  "const基本使用" 1 - (void)viewDidLoad { 2 [super viewDidLoad]; 3 4 // 定义变量 5 int a = 1; 6 7 // 允许修改值 8 a = 20; 9 10 // const两种用法11 // const:修饰基本变量p12 // 这两种写法是一样的,const只修饰右边的基本变量b13 const int b = 20; // b:只读变量14 int const b = 20; // b:只读变量15 16 // 会报错17 // 不允许修改值18 b = 1;19 20 // const:修饰指针变量*p,带*的变量,就是指针变量.21 // 定义一个指向int类型的指针变量,指向a的地址22 int *p = &a;23 24 int c = 10;25 26 p = &c;27 28 // 允许修改p指向的地址,29 // 允许修改p访问内存空间的值30 *p = 20;31 32 // const修饰指针变量访问的内存空间,修饰的是右边*p1,33 // 两种方式一样34 const int *p1; // *p1:常量 p1:变量35 int const *p1; // *p1:常量 p1:变量36 37 // const修饰指针变量p138 int * const p1; // *p1:变量 p1:常量39 40 41 // 第一个const修饰*p1 第二个const修饰 p142 // 两种方式一样43 const int * const p1; // *p1:常量 p1:常量44 45 int const * const p1; // *p1:常量 p1:常量46 47 } 三、const开发中使用场景: * 1.需求1:提供一个方法,这个方法的参数是地址,里面只能通过地址读取值,不能通过地址修改值 * 2.需求2:提供一个方法,这个方法的参数是地址,里面不能修改参数的地址。 1 @implementation ViewController 2 3 // const放*前面约束参数,表示*a只读 4 // 只能修改地址a,不能通过a修改访问的内存空间 5 - (void)test:(const int * )a 6 { 7 // *a = 20; 8 } 9 10 // const放*后面约束参数,表示a只读11 // 不能修改a的地址,只能修改a访问的值12 - (void)test1:(int * const)a13 {14 int b;15 // 会报错16 a = &b;17 18 *a = 2;19 }20 21 - (void)viewDidLoad {22 [super viewDidLoad];23 // Do any additional setup after loading the view, typically from a nib.24 25 int a = 10;26 27 // 需求1:提供一个方法,这个方法的参数是地址,里面只能通过地址读取值,不能通过地址修改值。28 29 // 这时候就需要使用const,约束方法的参数只读.30 [self test:&a];31 32 // 需求2:提供一个方法,这个方法的参数是地址,里面不能修改参数的地址。33 [self test1:&a];34 }35 36 @end 四、static和extern简单使用(要使用一个东西,先了解其作用) * "static作用": * 修饰局部变量: 1.延长局部变量的生命周期,程序结束才会销毁。 2.局部变量只会生成一份内存,只会初始化一次。 3.改变局部变量的作用域。 * 修饰全局变量 1.只能在本文件中访问,修改全局变量的作用域,生命周期不会改 2.避免重复定义全局变量 * "extern作用": * 只是用来获取全局变量(包括全局静态变量)的值,不能用于定义变量 * "extern工作原理": * 先在当前文件查找有没有全局变量,没有找到,才会去其他文件查找。 1 // 全局变量:只有一份内存,所有文件共享,与extern联合使用。 2 int a = 20; 3 4 // static修饰全局变量 5 static int age = 20; 6 7 - (void)test 8 { 9 // static修饰局部变量10 static int age = 0;11 age++;12 NSLog(@"%d",age);13 }14 15 - (void)viewDidLoad {16 [super viewDidLoad];17 // Do any additional setup after loading the view, typically from a nib.18 19 20 [self test];21 [self test];22 23 extern int age;24 NSLog(@"%d",age);25 }  五、static与const联合使用 * static与const作用:声明一个只读的静态变量 * 开发使用场景:在"一个文件中"经常使用的字符串常量,可以使用static与const组合 1 // 开发中常用static修饰全局变量,只改变作用域 2 3 // 为什么要改变全局变量作用域,防止重复声明全局变量。 4 5 // 开发中声明的全局变量,有些不希望外界改动,只允许读取。 6 7 // 比如一个基本数据类型不希望别人改动 8 9 // 声明一个静态的全局只读常量10 static const int a = 20;11 12 // staic和const联合的作用:声明一个静态的全局只读常量13 14 // iOS中staic和const常用使用场景,是用来代替宏,把一个经常使用的字符串常量,定义成静态全局只读变量.15 16 // 开发中经常拿到key修改值,因此用const修饰key,表示key只读,不允许修改。17 static NSString * const key = @"name";18 19 // 如果 const修饰 *key1,表示*key1只读,key1还是能改变。20 21 static NSString const *key1 = @"name";  六、extern与const联合使用 * 开发中使用场景:在"多个文件中"经常使用的同一个字符串常量,可以使用extern与const组合。 * 原因: * static与const组合:在每个文件都需要定义一份静态全局变量。 * extern与const组合:只需要定义一份全局变量,多个文件共享。 *  全局常量正规写法:开发中便于管理所有的全局变量,通常搞一个GlobeConst文件,里面专门定义全局变量,统一管理,要不然项目文件多不好找。 * GlobeConst.h
/*******************************首页****************************/extern NSString * const nameKey = @"name";/*******************************首页****************************/
  * GlobeConst.m 1 #import
2 3 /*******************************首页****************************/4 5 NSString * const nameKey = @"name";6 7 8 /*******************************首页****************************/  

转载地址:http://swwhf.baihongyu.com/

你可能感兴趣的文章
BaseServiceImpl中的实现关键点
查看>>
Struts2中的session、request、respsonse获取方法
查看>>
如何理解MVC模型
查看>>
SpringMVC中乱码解决方案
查看>>
SpringMVC中时间格式转换的解决方案
查看>>
post和get请求相关知识点
查看>>
关于try finally 中的return语句的问题
查看>>
RequestBody/ResponseBody处理Json数据
查看>>
springmvc请求参数获取的几种方法
查看>>
在eclipse中创建和myeclipse一样的包结构
查看>>
Java中的IO流
查看>>
java中的关键字
查看>>
如果某个方法是静态的,它的行为就不具有多态性
查看>>
优化Hibernate所鼓励的7大措施
查看>>
Java 8系列之重新认识HashMap
查看>>
HashMap 、 ArrayList、String 重写了equals方法 而Object类(比如User)没有重写
查看>>
Servlet的生命周期
查看>>
Object中的getClass()返回的是当前运行的类
查看>>
加载驱动程序的方法
查看>>
深入理解java异常处理机制
查看>>