美文网首页
关键字的理解以及使用const/static/extern

关键字的理解以及使用const/static/extern

作者: 远航的移动开发历程 | 来源:发表于2016-11-16 11:06 被阅读74次

    一、前言

    阅读别人的代码(一些优秀的源码)总能发现一些常见的关键字,随着编程经验的积累大部分还是知道是什么意思的,但在概念上和具体的用法上却依然有些模糊,故特意整理汇总了下三个比较常见的关键字——const/static/extern。

    二、关键字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=1

    2016-10-26 14:58:49.044 fff[2760:170260] i=1

    2016-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=1

    2016-10-26 15:07:35.347 fff[2817:175155] i=2

    2016-10-26 15:07:35.761 fff[2817:175155] i=3

    2016-10-26 15:07:36.057 fff[2817:175155] i=4

    2016-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;

    这样,只要导入头文件,就可以全局的使用定义的变量或常量。

    备注:我的理解也是这样的就不在自己去叙述了。附上原创链接:  http://www.cocoachina.com/ios/20161110/18035.html

    extern 与 define 区别

    定义常量有两种方法:

    最简单的方法:

    // Prefs.h#definePREFS_MY_CONSTANT@"prefs_my_constant"

    更好的方法:

    // Prefs.hexternNSString*constPREFS_MY_CONSTANT;// Prefs.mNSString*constPREFS_MY_CONSTANT=@"prefs_my_constant";

    用第二种更好些

    define只是简单的替换,又称作宏定义、预处理命令。

    而const是要分配内存空间的,提示编译器遇到此变量和函数时在其他模块中寻找其定义

    还有就是#define是不会对数据类型进行检查的,而第二种会对数据类型进行安全检查、

    使用#define(相当于使用@""写法的“字面量”)不能在shared libraries的情况下保证得到的字符串地址是一样的。String Programming Guide中也有描述 "The compiler makes such object constants unique on a per-module basis, and they’re never deallocated."可见使用@""的写法是在编译期就把字符串实例已经生成好的。

    @""写法的字符串会在编译期被替换成NSConstantString的实例,NSString也是唯一一种可以在编译期被实例化的类。

    所以在shared libraries的情况下,

    如果用@""的字符串作为dictionary的key的话,会导致它需要做isEqualToString的比较,如果用extern

    NSString * const,只要做指针的比较。显然指针比较比逐个字符比较快多了。

    所以如果需要作为dictionary的key的话,使用extern NSString * const的写法,要比@""的写法(也就是用#define)更好。

    备注:原创http://blog.csdn.net/gaoyuqiang30/article/details/48389369

    相关文章

      网友评论

          本文标题:关键字的理解以及使用const/static/extern

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