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

最近看了一篇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文件进行调用。

欢迎关注我的个人微信公众号,免费送计算机各种最新视频资源!你想象不到的精彩!


0.jpg

推荐阅读更多精彩内容