iOS - const与static与extern

作者: SkyMing一C | 来源:发表于2018-01-05 17:59 被阅读22次
    图片源于网络

    1. const

    const意为"常量"。

    程序中,"常量"的值是不变的,固定的

    • 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修饰基本数据变量
      //声明一个int类型的变量a,变量初始化值为10,并且变量a左边有一个const关键字修饰
      
      int  const  a = 10;
      const  int   a1 = 10;
      
      //两种写法是一样的,const只修饰右边的基本变量,让其只读
      
      //因为变量a被const修饰,就成为了只读,不能被修改赋值了,所以下面这行代码是错误的
      
      //a = 20;//错误代码,编译器报错
      
      
      • const修饰指针变量

        • const在 * 后时,var变量的内存指针将不能指向其他内存,同时内存块中的内容也将保持不变。
        // const在* 后
        NSString * const var = @"11";
        var = @"12"; // 编译器报错
        *var = @"12"; // 编译器报错
        
        • const在 * 前时,var变量的内存指针同样无法指向其他内存块,但是在这种情况下,var的内存块的内存是可以发生变化的。
        //内存指针同样无法指向其他内存块
        
        //var的内存块的内存是可以发生变化
        NSString const * var = @"11";
        *var = @"12"; // 编译器报错
        var = @"12";  // 编译器不报错
        /*
          @"" 与[[NSString alloc]init];等价
          @[] 与[[NSArray alloc]init];等价
          @{} 与[[NSDictionary alloc]init];等价
        */
        //用字面量语法对一个变量赋值时相当于对他重新开辟了内存块
        
        • const在声明字符串的用法
          NSString * const SKYName = @"sky";
        
    • 使用static const修饰变量和宏定义的比较

      • 编译时刻:宏是预编译(编译之前处理),const是编译阶段。

      • 编译检查:宏不做检查,不会报编译错误,只是替换,const会编译检查,会报编译错误。

      • 宏的好处:宏能定义一些函数,方法。 const不能。

      • 宏的坏处:使用大量宏,容易造成编译时间久,每次都需要重新替换。

      • 在确定了使用的常量类型,及常量值时使用 const 进行定义;而简单的函数,或传参字符串等高级定义时,则使用 define 进行宏定义。

    2. static

    static意为"静态"

    • 修饰局部变量

      • 让局部变量只初始化一次

      • 局部变量在程序中只有一份内存

      • 并不会改变局部变量的作用域,仅仅是改变了局部变量的生命周期,也就是说生命周期类似全局变量了,但是作用域不变(只到程序结束,这个局部变量才会销毁)

      for (NSInteger i = 0; i < 10; i++) {
         
         //声明一个局部变量i
         
         NSInteger j = 0;    //每次点击view来到这个方法时让i自增
         
         j ++;    //打印结果
         NSLog(@"j%=ld",j);
         /*
           打印结果
             j=1
             j=1
             j=1
             j=1
             j=1
             j=1
             j=1
             j=1
             j=1
             j=1
         */
      }
      
      • 解释:j一直等于1,这也是预料之中的,因为每次点击进入这个方法就会重新初始化一个全新的变量j = 0,加加了一次后值变为1,然后打印出结果为1,出了这个方法后局部变量j就被释放回收。所以每次打印出来的结果都为1。
      for (NSInteger i = 0; i < 10; i++) {
          
          //声明一个局部变量i
          
          static NSInteger j = 0;    //每次点击view来到这个方法时让i自增
          
          j ++;    //打印结果
          NSLog(@"j%=ld",j);
          /*
            打印结果
              j=1
              j=2
              j=3
              j=4
              j=5
              j=6
              j=7
              j=8
              j=9
              j=10
          */
      }
      
      • 解释:i的值一直在自增。这就是关键字static修饰的局部变量的作用,让局部变量永远只初始化一次,一份内存,生命周期已经跟全局变量类似了,只是作用域不变
    • 修饰全局变量

      • 全局变量的作用域仅限于当前文件
      static SVProgressHUD *sharedView;
      + (SVProgressHUD*)sharedView {
       static dispatch_once_t once;
      #if !defined(SV_APP_EXTENSIONS)
         dispatch_once(&once, ^{ sharedView = [[self alloc] initWithFrame:[[[UIApplication sharedApplication] delegate] window].bounds]; });
      #else
         dispatch_once(&once, ^{ sharedView = [[self alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; });
      #endif
         return sharedView;
      }
      
      
    • static和const联合使用

    static const CGFloat SVProgressHUDParallaxDepthPoints = 10.0f;
    static const CGFloat SVProgressHUDUndefinedProgress = -1;
    static const CGFloat SVProgressHUDDefaultAnimationDuration = 0.15f;
    static const CGFloat SVProgressHUDVerticalSpacing = 12.0f;
    static const CGFloat SVProgressHUDHorizontalSpacing = 12.0f;
    static const CGFloat SVProgressHUDLabelSpacing = 8.0f;
    

    3. extern

    extern意为"外面的、外部的"

    • 声明外部全局变量,常与const联合使用

      • 声明全局常量
      //  SVProgressHUD.h
      //声明一些全局常量
      
      extern NSString * _Nonnull const  SVProgressHUDDidReceiveTouchEventNotification;
      extern NSString * _Nonnull const SVProgressHUDDidTouchDownInsideNotification;
      extern NSString * _Nonnull const SVProgressHUDWillDisappearNotification;
      extern NSString * _Nonnull const SVProgressHUDDidDisappearNotification;
      extern NSString * _Nonnull const SVProgressHUDWillAppearNotification;
      extern NSString * _Nonnull const SVProgressHUDDidAppearNotification;
      
      extern NSString * _Nonnull const SVProgressHUDStatusUserInfoKey;
      
      • 实现全局常量
      //  SVProgressHUD.m
      //实现全局常量
      NSString * const SVProgressHUDDidReceiveTouchEventNotification = @"SVProgressHUDDidReceiveTouchEventNotification";
      NSString * const SVProgressHUDDidTouchDownInsideNotification = @"SVProgressHUDDidTouchDownInsideNotification";
      NSString * const SVProgressHUDWillDisappearNotification = @"SVProgressHUDWillDisappearNotification";
      NSString * const SVProgressHUDDidDisappearNotification = @"SVProgressHUDDidDisappearNotification";
      NSString * const SVProgressHUDWillAppearNotification = @"SVProgressHUDWillAppearNotification";
      NSString * const SVProgressHUDDidAppearNotification = @"SVProgressHUDDidAppearNotification";
      
      NSString * const SVProgressHUDStatusUserInfoKey = @"SVProgressHUDStatusUserInfoKey";
      
    extern const与 #define
    • #define写法
     #define SVProgressHUDDidReceiveTouchEventNotification  @"SVProgressHUDDidReceiveTouchEventNotification"
    
    • extern const写法
    //  SVProgressHUD.h
    extern NSString * _Nonnull const  SVProgressHUDDidReceiveTouchEventNotification;
    
    //  SVProgressHUD.m
    NSString * const SVProgressHUDDidReceiveTouchEventNotification = @"SVProgressHUDDidReceiveTouchEventNotification";
    
    • #define只是简单的替换,又称作宏定义、预处理命令。

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

    • #define是不会对数据类型进行检查

    • extern 与const联合使用时,是会对数据类型进行安全检查

    • 在shared libraries的情况下,#define(相当于使用@""写法的“字面量”)不能保证得到的字符串地址是一样的。如果用@""的字符串作为dictionary的key的话,会导致它需要做isEqualToString的比较

    • 在shared libraries的情况下,用extern NSString * const,只要做指针的比较。显然指针比较比逐个字符比较快多了。

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

    参考

    static和const的使用

    extern 与 define 区别

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

    【如何正确使用const,static,extern】|那些人追的干货

    相关文章

      网友评论

        本文标题:iOS - const与static与extern

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