objectc语法-常量
在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修饰位置不同,代表什么?
2.NSString const *HSCoder = @"汉斯哈哈哈";
3.NSString * const 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中访问:
这⾥写图⽚描述
作者:汉斯哈哈哈
链接:www.jianshu/p/f83335e036b5
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,⾮商业转载请注明出处。
最近在读⼀本effecttive  2.0 ---- 编写⾼质量与OS X代码的52个有效⽅法
笔者在这⾥记录⼀些⽐较好⽤的⽅法和技巧,如有错误或者疏漏,欢迎⼤家指正.
1. 编写代码时经常要定义常量, 例如, 要写⼀个UI视图类, 此视图显⽰出来之后就播放动画, 然后消失. 你可能想把播放动画的时间提取为常量.也许会⽤这种⽅法来做:
#define ANIMATION_DURATION 0.3;
上述的预处理指令会把源代码中的ANIMATION_DURATION 字符串替换成0.3, 这确实可以实现,但是这样定义出来的变量没有类型信息. 动画的持续播放时间应该是NSTimeInterval类型, 此外预处理过程会把碰到所有的ANIMATION_DURATION ⼀律换成0.3,假设此指令声明在,某个头⽂件中, 那么所有引⼊这个头⽂件的代码, 其ANIMATION_DURATION都会被替换成0.3, 这很显然不够好,
2.有个办法预处理指令来定义常量会更好:
static const NSTimeInterval kAnimationDuration = 0.3;
这种⽅式定义的常量包含了类型信息,清楚的描述了常量的含义.可知常量的类型, 如果定义很多常量的话,清晰明了不会觉得很乱.
还要注意命名规范:如果只是⽂件内使⽤,就在命名前⾯加上k; 若在类之外⽤, 就⽤类名作为前缀.
尽量不要在头⽂件(.h⽂件)中定义常量, 在实现⽂件(.m⽂件)中定义常量
变量⼀定要同时⽤static与const来声明. const修饰符不让其他⼈修改所声明的变量, 变量值改变的话编译器就会报错, static修饰符意味着该变量仅在此变量的编译单元(某个类的.m⽂件)可见, 作⽤域仅限于.m⽂件中, 假如声明变量时不加static的话, 编译器会为它创建⼀个"外部符号", 如果其他⽂件重名的话就会报错,
3. 全局变量:如果需要对外公开某个常量,⽐如通知中⼼注册对象name唯⼀且全局,这个字符串来可以声明⼀个外界课件的常值变量.此类常量需放在"全局符号表"global symbol table中, 以便可以在定义该常量的编译单元之外使⽤,定义与static const 不同:
// 在头⽂件 .h⽂件中
extern NSString *const  XYStringConstant;
// 在实现⽂件 .m⽂件中
NSString *const  XYStringConstant = @"VALUE";
在常量的头⽂件中(.h⽂件)声明, 且在实现⽂件中(.m⽂件)定义.注意const修饰符的位置
extern 关键字:告诉编译器, 在全局符号表中有⼀个叫XYStringConstant的符号, 即编译器⽆须查看其定义, 允许代码使⽤此常量.
此类常量必须要定义, ⽽且只能定义⼀次(.m⽂件实现),实现⽂件⽣成⽬标⽂件时, 编译器会在"数据段"为字符串分配存储空间,链接器会把此⽬标⽂件与其他⽬标⽂件相链接⽣成最终的⼆进制⽂件.凡是⽤到该常量的时候, 链接器都将其解析.
[objc]
1. #import <UIKit/UIKit.h>
2.
3.
4. extern NSString *const XYLoginMangerDidLoginNotification;
5.
6. @interface XYViewController : UIViewController
7.
8. @end
[objc]
1. #import "XYViewController.h"
2.
3. NSString *const XYLoginMangerDidLoginNotification = @"XYLoginMangerDidLoginNotification";
4.
5. @implementation XYViewController
6.
7. - (void)viewDidLoad {
8.    [super viewDidLoad];
9.    // Do any additional setup after loading the view.
10. }
11.
12. - (void)didReceiveMemoryWarning {
13.    [super didReceiveMemoryWarning];
14.    // Dispose of any resources that can be recreated.
15. }
注意常量的名字,避免名称冲突(建议命名规范,看系统内部命名)
4. 总结:
1.不要⽤预处理指令定义常量,这样定义出来的常量不含类型信息,编译器只是会在编译前执⾏查替换操作.即使有⼈重新定义了常量值,编译器也不会产⽣警告信息, 这将会导致程序中的常量值不⼀致.字符串常量是字符常量吗
2.在实现⽂件中使⽤static const定义"只在实现⽂件中可见的常量'由于此类常量不在全局符号表中, 所以⽆需为其名称加前缀.
3.在头⽂件中使⽤extern来声明全局变量, 并在相关实现⽂件中定义其值, 这种常量要出现在全局符号表中, 所以其名称应加以区隔, 通常⽤与之相关的类名做前缀
-------

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。