美文网首页iOS开发iOS开发杂货铺iOS精英班
iOS 宏(define)与常量(const)的正确使用

iOS 宏(define)与常量(const)的正确使用

作者: 汉斯哈哈哈 | 来源:发表于2015-08-10 18:54 被阅读50689次

    在iOS开发中,经常用到宏定义,或用const修饰一些数据类型,经常有开发者不知怎么正确使用,导致项目中乱用宏与const修饰

    你能区分下面的吗?知道什么时候用吗?

    #define HSCoder @"汉斯哈哈哈"
    NSString *HSCoder = @"汉斯哈哈哈";
    extern NSString *HSCoder;
    extern const NSString *HSCoder;
    
    static const NSString *HSCoder = @"汉斯哈哈哈";
    
    const NSString *HSCoder = @"汉斯哈哈哈";
    NSString const *HSCoder = @"汉斯哈哈哈";
    NSString * const HSCoder = @"汉斯哈哈哈";
    

    当我们想全局共用一些数据时,可以用宏、变量、常量

    宏:

    
    #define HSCoder @"汉斯哈哈哈"
    
    

    变量:

    NSString *HSCoder = @"汉斯哈哈哈";
    

    常量:

    四种写法:
    static const NSString *HSCoder = @"汉斯哈哈哈";
    const NSString *HSCoder = @"汉斯哈哈哈";
    NSString const *HSCoder = @"汉斯哈哈哈";
    NSString * const HSCoder = @"汉斯哈哈哈";
    

    思考:宏与常/变量的选择?

    • 宏:只是在预处理器里进行文本替换,没有类型,不做任何类型检查,编译器可以对相同的字符串进行优化。只保存一份到 .rodata 段。甚至有相同后缀的字符串也可以优化,你可以用GCC 编译测试,"Hello world" 与 "world" 两个字符串,只存储前面一个。取的时候只需要给前面和中间的地址,如果是整形、浮点型会有多份拷贝,但这些数写在指令中。占的只是代码段而已,大量用宏会导致二进制文件变大
    • 变量:共享一块内存空间,就算项目中N处用到,也不会分配N块内存空间,可以被修改,在编译阶段会执行类型检查
    • 常量:共享一块内存空间,就算项目中N处用到,也不会分配N块内存空间,可以根据const修饰的位置设定能否修改,在编译阶段会执行类型检查

    尽量使用const,看苹果api使用常量多点,如下图:


    这里写图片描述

    常量区分

    全局常量:不管你定义在任何文件夹,外部都能访问

    const NSString *HSCoder = @"汉斯哈哈哈";
    

    例如:

    在ViewController定义一个 HSCoder 字符串全局常量:


    这里写图片描述

    在AppDelegate中访问:


    这里写图片描述

    局部常量:用static修饰后,不能提供外界访问

    static const NSString *HSCoder = @"汉斯哈哈哈";
    

    例如:

    在ViewController定义一个 HSCoder 字符串局部常量:


    这里写图片描述

    编译时报错:


    这里写图片描述

    const修饰位置不同,代表什么?

    1.const NSString *HSCoder = @"汉斯哈哈哈";
    2.NSString const *HSCoder = @"汉斯哈哈哈";
    3.NSString * const HSCoder = @"汉斯哈哈哈";
    
    1.const NSString *HSCoder = @"汉斯哈哈哈";
    "*HSCoder"不能被修改, "HSCoder"能被修改
    
    2.NSString const *HSCoder = @"汉斯哈哈哈";
    "*HSCoder"不能被修改, "HSCoder"能被修改
    
    3.NSString * const HSCoder = @"汉斯哈哈哈";
    "HSCoder"不能被修改,"*HSCoder"能被修改
    
    注意:1和2其实没什么区别
    

    结论:const右边的总不能被修改

    验证:

    const int *p;
    
    这里写图片描述
    int const *p;
    
    这里写图片描述
    int * const p;
    
    这里写图片描述

    所以一般我们定义一个常量又不想被修改应该这样:

    NSString * const HSCoder = @"汉斯哈哈哈";
    

    测试:

    在ViewController定义一个常量HSCoder:


    这里写图片描述

    在AppDelegate修改常量HSCoder,看下面报错提示:


    这里写图片描述

    一般项目中,定义全局常量,会写在独立文件里

    HSConst.m 定义常量:


    这里写图片描述

    HSConst.h 提供外接访问常量:


    这里写图片描述

    在AppDelegate中访问:


    这里写图片描述

    文章同步到微信公众号:hans_iOS 有疑问可以在公众号里直接发

    相关文章

      网友评论

      • LD_左岸:有个问题请教下啊如果工程里所有的接口 都写在这个类里 HSConst.m 里的ip不能写成动态的啊
        比如我想这么写 NSString * const LoginAPI = [NSString stringWithFormat:@"%@",@""];
        不成啊
      • EchoZuo:不错不错,学习了~

        不错关于宏这一部分“宏:只是在预处理器里进行文本替换,没有类型,不做任何类型检查,编译器可以对相同的字符串进行优化。只保存一份到 .rodata 段。甚至有相同后缀的字符串也可以优化,你可以用GCC 编译测试,"Hello world" 与 "world" 两个字符串,只存储前面一个。取的时候只需要给前面和中间的地址,如果是整形、浮点型会有多份拷贝,但这些数写在指令中。占的只是代码段而已,大量用宏会导致二进制文件变大”

        还不是特别明白。。。如果能够更详细的讲解下或者有更详细的资料链接就更好了
      • 7a946bf5d2ca:const修饰位置不同,代表什么? 验证的时候为什么不能用NSString 只能用int?
      • 狼人王:static const Nstring*cellId=@"";这个可以再vc里面调用啊,你为啥说是错的群主
      • 云逸枫林:解惑了 多谢
      • Link913:楼主你好,为什么这么写连接器报错呢,我写在头文件再倒入pch文件
        const NSString * JLoginNotification = @"JLoginNotification";
      • 凯文Kevin21:厉害了,我的哥。
      • 酷哥不回头看爆炸:请问 FOUNDATION_EXPORT 和 UIKIT_EXTERN 的区别是什么呢?
      • Coder_Melo:忘了,回头来看看!写得很棒
      • FaiChou:一般项目中,定义全局常量,会写在独立文件里

        HSConst.m 定义常量

        HSConst.h 提供外接访问常量:

        请问,为什么在HSConst.m中import的是UIKit而不是HSConst.h,我在MJRefresh中也发现是这么用的。请教。

        中秋节快乐哈 :smile:
      • 南方小金豆:如果一个url ,根据不同的判断选择赋予不同的值。怎么定义好
        南方小金豆:@清蒸鱼跃龙门 我现在也是这样用的,感觉很不方便。 例如:如果数据请求url 有多个测试环境,就有多个url。还想要全局根据服务器返回的字段来配置https的话,很难搞。最后是写了个方法来配置...不知道你有什么好的建议
        清蒸鱼跃龙门:@那份牵挂给了谁
        #define isTrueEnvironment 0

        #if isTrueEnvironment

        #pragma mark- 真实环境
        #define SERVER_URL @"http://bbb.bbb.com/Api/"

        #else

        #pragma mark- 测试环境
        #define SERVER_URL @"http://aaa.aaa.com/Api/"

        #endif
        清蒸鱼跃龙门:@那份牵挂给了谁 宏定义
      • Lol刀妹:可以,很强势
      • 7e5ed2c6e212:学习了 赞一个~
      • 郑明明:可以的
      • 郑明明:很详细
      • karthus:写的很细节 感谢
      • 檀羽冲:同问,创建的这个独立的文件HSConst.h和HSConst.m是继承于什么
        DSperson:@檀羽冲 NSObject
        汉斯哈哈哈:@檀羽冲 方便管理项目中的所有常量
      • A_sura:作者写的挺好的,看了后解了我的一些疑问,赞一个
      • dongwenbo:学习了
      • wg689:既然定义宏一般不想被更改,使用宏可能会被更改引起不必要的麻烦,貌似和分配内存没关系
      • 路与心:你创建的这个独立的文件HSConst.h和HSConst.m是继承于什么
        ec200686b10b:@路与心 NSObject
      • Code_Ninja:看到这里:
        3.NSString * const HSCoder = @"汉斯哈哈哈";
        "HSCoder"不能被修改,"*HSCoder"能被修改

        测试了一下,*HSCoder不能被修改啊,请问怎么修改?

        发现数值类型的,这样写是没问题的。
        7a946bf5d2ca:定义一个常量字符串 到底const应该放在*号前面还是后面啊 不知*HSCoder是什么 取值?
        618e89071db3:OC内部机制吧 C语言字符串不是用NSString来表示 数值类型没问题是因为和C基本一致(其实调的是C语言语法)
        5947a405aad4:我也发现不能修改, 为啥呢?
      • 码农甲:我觉得你理解错了

        extern NSString * const HSCoder 才会分配内存
        水平:@一只名叫心蓝的猫 extern 只是声明变量 不会分配内存吧
      • 啃手高手:学习了
      • iOS程序犭袁:学习了
        wg689:@iOS程序犭袁 龙哥 写篇文章 大牛是如何炼成的,或者分享下 你是如何成长的
      • UItachi:应该顺便把extern拿出来说说
      • 9ae0682726c6:归纳的简单明了 赞
      • 七夜98:不错
      • 奔奔奔跑:涨姿势
      • 汉斯哈哈哈:@Je_amo 互相学习😋
      • Lonely__M:好东西,涨姿势了
      • ZeroDY:请问既然不鼓励使用宏,为什么最后要用UIKIT_EXTERN呢
        公爵海恩庭斯:@WOWBingo 并不是不鼓励使用宏,而是不鼓励使用宏来定义常量。因为使用宏来定义常量容易带来一些不必要的麻烦,比如运算的时候。
        ZeroDY:@汉斯哈哈哈 回答的机智 :joy:
        汉斯哈哈哈:@WOWBingo 不鼓励也并不是不能用 :smile:
      • yangguang1029:1.宏会分配内存空间?不是预编译的时候直接替换吗?如果分配内存空间,那就意味着是C++中的左值了,宏肯定不是左值吧
        2.static的作用是限定其可见范围只在本文件内,当然要理解成是否是全局,也许没问题。假如在头文件中定义一个static const 变量,那只要include了这个头文件,就都可以使用,只不过不再是同一个变量了

        个人见解~如有错误欢迎讨论~
        汉斯哈哈哈:@WOWBingo 就我目前理解,const效率有可能会高点,如果宏定义整形,浮点型,会有多份拷贝,多个拷贝不是说占更多内存,这些数写在指令中
        汉斯哈哈哈:@yangguang1029 谢谢指点!宏只是在预处理器里进行文本替换,跟分配内存无关系
        ZeroDY:@yangguang1029 我也不明白,你可以看一下这里http://blog.csdn.net/love_gaohz/article/details/7567856
        这里说宏每次替换的时候分配一次内存,好像是const效率高些

      本文标题:iOS 宏(define)与常量(const)的正确使用

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