美文网首页iOSoc基础iOS开发基础篇
OC中关键字extern、static、const探究

OC中关键字extern、static、const探究

作者: Peak_One | 来源:发表于2016-03-18 14:27 被阅读4841次

    最近看了一篇blog:http://www.jianshu.com/p/2fd58ed2cf55 主要讲的就是这三个关键字的使用(以前自己从不用这几个关键字,是不是很low?),博主写的很好,在此致敬。但是我发现我对其中的extern、static理解不了,于是,自己爬网,总结了一下。希望对大家有帮助。

    extern

    extern(只能用来修饰全局变量)是一个大家很常见的东西,很多的第三方中都会出现这个关键字,以前只知道大概是跨文件引用的,其余的就基本不知道。废话少说,进入正题。对于extern我主要从三个方面来讲解。
    1. 与.h文件的关系
    2. extern引用变量
    3. extern声明

    1.与.h文件的关系
    .h的用法:想必大家都很了解了,是为了更好的方便其他文件(类)去调用本文件中的变量、属性和方法。而extern也是为了实现变量和函数的跨文件引用。所以很有必要详细讲解一下.h文件和extern的用法。
    对于.h文件,我想大家都很熟悉了,不做过多的解释,但是有一点很重要:如果你在.h文件中声明全局变量(在OC中是不合法的:主要指在@interface ExternModel : NSObject和@end之间,当然如果在他们两个之外也是可以声明的)代码如下:

    这是一个.h文件
    #import <Foundation/Foundation.h>
    @interface ExternModel : NSObject
      //  这个是不合法的:因为OC的类会将这个全局变量当做成员属性来处理,而成员属性是需要加{}的,所以不合法
          NSString *lhString;//声明全局变量的时候默认带有extern,这里必须显式声明
    @end
    

    所以正确的写法应该是:(如果还在.h中声明全局变量)

    #import <Foundation/Foundation.h>
    @interface ExternModel : NSObject
         extern NSString *lhString;//这里由于带有extern所以会被认为是全局变量
    @end
    
    常用用法(.h结合extern联合使用):
    1. 如果在.h文件中声明了extern全局变量,那么在同一个类中的.m文件对全局变量的赋值必须是:数据类型+变量名(与声明一致)=XXXX结构。并且在调用的时候,必须导入.h文件。代码如下:
    

    ExternModel.h

    #import <Foundation/Foundation.h>
    @interface ExternModel : NSObject
          extern NSString *lhString;
    @end
    

    ExternModel.m

    #import "ExternModel.h"
    @implementation ExternModel
           NSString *lhString=@"hello";
    @end
    

    调用的时候:例如:在viewController.m中调用,则可以引入:ExternModel.h,否则无法识别全局变量。当然也可以通过不导入头文件的方式进行调用(通过extern调用)。

    1. extern引用变量
      extern具备与.h文件很相似的跨文件访问的功能,但是.h文件不单单局限于范文全局变量,而extern则必须是全局变量(静态+非静态)。
      如果在其他文件中访问一个类的全局变量,可以不用导入.h文件,通过extern去直接访问。
      例子:同样还是在ViewController.m中访问,此时不需要去导入头文件,代码如下(此时ExternModel代码如上):
      #import "ViewController.h"

      @interface ViewController ()
      
      @end
      
      @implementation ViewController
      
      - (void)viewDidLoad {
            [super viewDidLoad];
             extern NSString *lhString;
             NSLog(@"%@",lhString);
      }
      @end
      

    输出结果:
    2016-03-18 13:37:45.404 ExternTest[1490:180870] hello
    可见在不通过.h的情况下去访问全局变量,可以通过extern实现。

    1. extern声明
      extern声明,仅适于修饰全局变量,不能去修饰其他的变量。一般情况下默认,定义的全局变量都带有extern,所以不过多解释。
    const

    const是用来修饰常量的,这一点注意与宏的区别(苹果推荐我们不要将字符串常量抽成宏):
    (以下总结引用自:http://www.jianshu.com/p/2fd58ed2cf55 因为总结的很好)

    1.编译时刻:宏是预编译(编译之前处理),const是编译阶段。
    
    2.编译检查:宏不做检查,不会报编译错误,只是替换,const会编译检查,会报编译错误。
    
    3.宏的好处:宏能定义一些函数,方法。 const不能。
    
    4.宏的坏处:使用大量宏,容易造成编译时间久,每次都需要重新替换。
    

    const的介绍:
    1. const仅仅用来修饰右边的变量(基本数据变量p,指针变量*p)
    2. 被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 = &c; 
    
              // 允许修改p指向的地址 
              // 允许修改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:常量
     }
    
    static修饰全局变量

    1.在全局变量前加static,全局变量就被定义成为一个全局静态变量(全局变量和静态全局变量的生命周期是一样的,都是在堆中的静态区,在整个工程执行期间内一直存在)
    特点如下:
    1)存储区:静态存储区没变(静态存储区在整个程序运行期间都存在);
    2)作用域:全局静态变量在声明他的文件之外是不可见的。准确地讲从定义之处开始到文件结尾。非静态全局 变量的作用域是整个源程序(多个源文件可以共同使用); 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。

     好处:   
    1)不会被其他文件所访问,修改;
    2)其他文件中可以使用相同名字的变量,不会发生冲突。
    

    2.static修饰局部变量
    在局部变量之前加上关键字static,局部变量就被定义成为一个局部静态变量。
    特点如下:
    1)存储区:有栈变为静态存储区rw data,生存期为整个源程序,只能在定义该变量的函数内使用。退出该函数后, 尽管该变量还继续存在,
    但不能使用它;
    2)作用域:作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域随之结束。

    3.static修饰函数
    在函数的返回类型前加上关键字static,函数就被定义成为静态函数。
    函数的定义和声明默认情况下是extern的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。只能被本文件中的函数调用,而不能被同一程序其它文件中的函数调用
    好处:
    1)其他文件中可以定义相同名字的函数,不会发生冲突
    2) 静态函数不能被其他文件所用。
    在我们这篇博客中主要关注于OC中三个关键字的常用方法。以下将是OC中常用方法的总结:

    static和const的联合使用
    • static与const作用:声明一个只读的静态变量
    • 开发使用场景:在一个文件中经常使用的字符串常量,可以使用static与const组合
      具体参考bolg:http://www.jianshu.com/p/2fd58ed2cf55 中的static与const的联合使用
    extern和const的联合使用
       作用:extern与const组合:只需要定义一份全局变量,多个文件共享。并且全局常量只被定义一次,分配一次内存空间。
    

    代码如下:
    ExternModel.h

      #import <Foundation/Foundation.h>
      @interface ExternModel : NSObject
          extern NSString * const lhString;
      @end
    

    ExternModel.m

      #import "ExternModel.h"
      @implementation ExternModel
           NSString * const lhString=@"hello";
      @end
    

    调用的时候通过导入.h文件进行调用。

    相关文章

      网友评论

      • 吃蘑菇De大灰狼:看了很多篇,总是一带而过,到这里我才大概extern是怎么用呢。
        Peak_One:@吃蘑菇De大灰狼 加油
      • 圆圆的兔子二点零:写得相当好了
      • Cuffy:mark
      • 酷酷的哀殿:'调用的时候:例如:在viewController.m中调用,则必须引入:ExternModel.h,否则无法识别全局变量。'

        可以不引入,直接使用下面的方法使用它

        extern NSString *lhString;
        NSLog(@"%@", lhString);
        酷酷的哀殿:@多LV信源 编译时,不会找,链接时,才会找
        多LV信源:extern 现在本文件中找, 然后再去其他文件里找, 是这样吗?
      • 酷酷的哀殿:‘对于.h文件,我想大家都很熟悉了,不做过多的解释,但是有一点很重要:如果你在.h文件中声明全局变量(在OC中是不合法的)代码如下:’

        这样说不太合适吧,给人一种 OC里面 .h 文件无法声明全局变量的暗示。实际上,是可以声明的。
        Peak_One:@酷酷的哀殿 你再看看是不是这样子说的
        Peak_One:@酷酷的哀殿 可以,我去补充一下,谢谢指正
      • 微pk笑:不错不错!!!
      • Joy___:支持 支持
      • 郑钦洪_:支持支持
      • wittyfan:mark,谢谢作者

      本文标题:OC中关键字extern、static、const探究

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