首先,预处理命令他不是一个常量!!!!我们来看一段代码 #define avatar @"60" if (false) { #define avatar @"80" } NSLog(avatar);
这段代码会输出多少,我们将“avatar”定义为了60,然后在一个永远不会执行的代码里面重新定义了“avatar”为80,if语句中的代码永远不会执行,但是在编译时期,编译器会编译这段代码,而这个时候编译器就会将avatar这个名字替换为@“80”,所以这段代码最后的输出结果就是80。 用const来定义一个常量const修饰符定义的变量是不可变的,比如说你需要定义一个动画时间的常量,你可以这么做: static const NSTimeInterval kAnimateDuration = 0.3; 当你试图去修改“ kAnimateDuration”的值的时候,编译器会报错。更加重要的是用这种方法定义的常量是带有类型信息的,而这点则是define不具备的。 也许你已经发现了,如果你像这样定义: static const NSString * kUserName = @"StrongX"; 你是可以修改userName的值的,(说好的常量呢~~~) 首先我们需要确定的是以下两种写法是一样的: static NSString const * kUserName = @"StrongX"; static const NSString * kUserName = @"StrongX"; 也就是说const放在类型前还是类型后是一样的效果。然后不同效果的是下面这种写法: static NSString * const kUserName = @"StrongX"; const 修饰的是他右边的部分,也就是说: static NSString const * kUserName = static NSString const (* kUserName ) static NSString * const kUserName = static NSString * const (kUserName)
当const修饰的是(userName)的时候,不可变的是userName;星号在C语言中表示 NSLog(@"内存地址: %x",& kUserName); kUserName = @"superXLX"; NSLog(@"内存地址: %x",& kUserName);
以上NSLog会打印*userName指向的内存块地址,而他的输出是:
我们已经发现当我们改变内存的内存的时候他的地址并没有发生改变,也就是说这是符合“const”修饰符的规定的。 static NSString * const kUserName = @"StrongX"; 我们则无法改变userName的值。 所以当我们需要定义一个不可变的常量的时候 ,我们还是需要将“const”修饰符放到“*”指针指向符后边才对。
NSString * const kUserName = @"StrongX"; 可能尽管文件之间并没有相互引用,不存在属性名重复的问题(因为这并不是一个属性,这是一个外部符号),但是编译器还是报错了:
定义工程中的全局变量
在我们的工程中一定会定义很多全局常量,很多人的做法是会创建一个“ constant.h”文件,在这个文件中用#define声明许多常量,然后将这个头文件引入“pch”文件中,不能说这么做不对,但是如同上面说的那样define可能被修改,当然在命名规范的情况下这种情况很少出现,并且这样做的效率很高。 extern NSString *const XUserName; 然后在“constants.m”中定义他: NSString *const XUserName = @"StrongX"; 用“extern”定义的常量必须也只能初始化一次,不满足必须以及只能一次的条件那么编译器就会提醒你。在定义全局变量的时候需要要注意你的命名,你可以使用规定好的前缀来命名。 “define”和“extern”各有各的优势,不过我个人还是比较推荐使用“extern”.(因为之前在一个工程中被define坑惨了——!)。 (责任编辑:好模板) |