在开发过程中我们经常会定义一些变量,一般情况下会使用#define 、static 、const、extern 它们之间有什么区别能,接下来就简单的讲讲
define 预处理,就是讲定义的宏标识替换为一个值,所有引入的这个宏标识都会替换为该值;
static声明的变量是静态变量,变量值改变过之后,保存这次改变,每次使用的时候都要读取一遍值;
const声明过得变量值是不可改变的,是readonly的属性,不可以改变变量的值;
extern字段使用的时候,声明的变量为全局变量,都可以调用,也有这样一种比较狭义的说法:extern可以扩展一个类中的变量到另一个类中;
一. 宏(#define)
#define ANIMATION_DURATION 0.3
上述预处理指令会把源代码中的ANIMATION_DURATION字符串替换为0.3。这可能就是你想要的效果,不过这样定义出来的常量没有类型信息。“持续”(duration)这个词看上去应该与时间有关,但是代码中又未明确指出。此外,预处理过程会把碰到的所有ANIMATION_DURATION一律替换成0.3,这样的话,假设此指令声明在某个头文件中,那么所有引入了这个头文件的代码,其ANIMATION_DURATION都会被替换,。同时定义很多的宏在项目中编译的时间也会增加。
二.static && const
1: static NSString * const kName = @"StrongX";
2: static const NSString * kName = @"StrongB";
const 修饰的是右边的部分,其值不会被改变
注意常量的名字。为避免名称冲突,最好是用与之相关的类名做前缀。系统框架中一般都这样做。例如UIKit就按照这种方式来声明用作通知名称的全局常量。其中有类似UIApplicationDidEnterBackgroundNotification与UIApplicationWillEnterForegroundNotification这样的常量名。但是在实现文件中定义我们就可以不用加前缀,因其“只在编译单元内可见的常量”
- 通常在定义全局变量的时候需要要注意你的命名,你可以使用规定好的前缀来命名,一般定义局部变量“K”前缀来定义
这个常量在头文件中“声明”,且在实现文件中“定义”。注意const修饰符在常量类型中的位置。常量定义应从右至左解读,所以在本例中,kName就是“一个常量,而这个常量是指针,指向NSString对象”。这与需求相符:我们不希望有人改变此指针常量,使其指向另一个NSString对象。
这样定义常量要优于使用#define预处理指令,因为编译器会确保常量值不变。一旦定义好,即可随处使用。而采用预处理指令所定义的常量可能会无意中遭人修改,从而导致应用程序各个部分所使用的值互不相同。
三.extern的用法
extern NSString *str = @”123”;
在头文件中使用extern来声明全局常量,并在相关实现文件中定义其值。这种常量要出现在全局符号表中,所以其名称应加以区隔,通常用与之相关的类名做前缀。
在A.h里边声明一个变量extern NSString *oneViewUrlstr = @”123”;
这样就声明了一个全局变量,在B.h里边同样写入代码extern NSString *str;然后再B.m里边直接打印str就可以打印出123来,使用的时候不需要导入A.h文件头,也不区分类是否已经创建等等因素。
总结:
不要用预处理指令(宏”define“)定义常量。这样定义出来的常量不含类型信息,编译器只是会在编译前据此执行查找与替换操作。即使有人重新定义了常量值,编译器也不会产生警告信息,这将导致应用程序中的常量值不一致。