#define avatar @"60" if (false) {#define avatar @"80" } NSLog(avatar);这段代码会输出多少,我们将“avatar”定义为了60,然后在一个永远不会执行的代码里面重新定义了“avatar”为80,if语句中的代码永远不会执行,但是在编译时期,编译器会编译这段代码,而这个时候编译器就会将avatar这个名字替换为@“80”,所以这段代码最后的输出结果就是80。
static const NSTimeInterval kAnimateDuration = 0.3;当你试图去修改“ kAnimateDuration”的值的时候,编译器会报错。更加重要的是用这种方法定义的常量是带有类型信息的,而这点则是define不具备的。
static const NSString * kUserName = @"StrongX";你是可以修改userName的值的,(说好的常量呢~~~)
static NSString const * kUserName = @"StrongX";static const NSString * kUserName = @"StrongX";
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的值。
NSString * const kUserName = @"StrongX";可能尽管文件之间并没有相互引用,不存在属性名重复的问题(因为这并不是一个属性,这是一个外部符号),但是编译器还是报错了:
他会告诉你在两个目标文件(.0文件是.m文件编译后的输出文件)有一个重复的符号。(OC中没有类似C++中的名字空间的概念)
所以当你在你自己的.m文件中需要声明一个只有你自己可见的局部变量(k开头)的变量的时候一定要同时使用“static”和“const”两个符号。
定义工程中的全局变量
在我们的工程中一定会定义很多全局常量,很多人的做法是会创建一个“ constant.h”文件,在这个文件中用#define声明许多常量,然后将这个头文件引入“pch”文件中,不能说这么做不对,但是如同上面说的那样define可能被修改,当然在命名规范的情况下这种情况很少出现,并且这样做的效率很高。
然而苹果更推荐另外一种做法:"extern",这样做的优势是保持常量绝对不会被修改,并且一定初始化还带有类型信息。
我们在"constants.h"文件中,声明常量:
extern NSString *const XUserName;然后在“constants.m”中定义他:
NSString *const XUserName = @"StrongX";用“extern”定义的常量必须也只能初始化一次,不满足必须以及只能一次的条件那么编译器就会提醒你。在定义全局变量的时候需要要注意你的命名,你可以使用规定好的前缀来命名。