一、const 关键字
const 用来修饰其右边的变量,可以是基本数据类型变量或指针变量
1.基本数据类型
例如:
const int a = 10;
int const b = 10;
上面两种形式声明的常量都是只读的。
2.指针类型
例如:
const NSString *name = @"xiaoming";
NSString const *name = @"xiaoming";
NSString *const name = @"xiaoming"; //这个并不是修饰指针,还是修饰一个变量
以上三种形式的常量定义,前两种意思相同,const修饰的是一个指针(*name),表示的意思是:指针是一个常量,只读,不能修该其指向的地址;但是name的值可以修改,也就是你可以通过 name = @“zhangsan” 的形式修改。
第三种表示name是一个常量,只读,不允许修改其值。
二、static 关键字
1.static 修饰局部变量
1)保证局部变量只被初始化一次,在整个程序的运行中只有一份内存,延长该变量的生命周期;这时的局部变量在生命周期上类似全局变量,但是,变量的本身的作用域不变,不能在外部访问该静态变量。
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
int num = 1;
num ++;
NSLog(@"%d",num);
}
日志输出:
2017-09-05 14:30:44.676 static_const_extern[30632:351713] 2
2017-09-05 14:30:44.837 static_const_extern[30632:351713] 2
2017-09-05 14:30:44.839 static_const_extern[30632:351713] 2
2017-09-05 14:30:45.061 static_const_extern[30632:351713] 2
可以看出:每次touchesBegan方法执行结束后,变量num被释放,再次执行时有初始化该变量
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
static int num = 1;
num ++;
NSLog(@"%d",num);
}
日志输出:
2017-09-05 14:31:57.063 static_const_extern[30658:352500] 2
2017-09-05 14:31:57.564 static_const_extern[30658:352500] 3
2017-09-05 14:31:58.068 static_const_extern[30658:352500] 4
2017-09-05 14:31:58.404 static_const_extern[30658:352500] 5
由日志可以看出:
1> 静态变量确实只初始化一次,对基本数据类型默认初始化为0
2> 静态变量在touchesBegan方法结束后并未被释放,生命周期延长
3> 静态变量的作用域不变,因为此时还是不能再touchesBegan方法外部访问该静态变量
2.static 修饰全局变量
1)全局变量和静态全局变量的区别
1> 如果程序只有一个源文件,这两者没有区别
2> 如果有多个源文件,相同名称的全局变量只能有一个,即使在不同的源文件中也不能重名,否则编译报错!如果两者同时为静态全局变量,即使名称相同,也不会编译报错,必须同时为静态变量!!
代码:
#import <Foundation/Foundation.h>
NSString *address = @"beijing";
@interface FirstObj : NSObject
@end
#import <Foundation/Foundation.h>
NSString *address = @"beijing";
@interface SecondObj : NSObject
@end
以上是定义在.h文件中,对于.m文件也是一样,此时编译器会报 linker error
但是如果都用static修饰后,就不会出问题
2> 对于某个源文件中的全局变量,可以通过extern方式在其他文件使用,但是对静态全局变量,extern 也无效
代码:
#import "FirstObj.h"
NSString *address = @"beijing"; //定义一个全局变量
@implementation FirstObj
@end
在其他文件中通过extern访问
#import "ViewController.h"
extern NSString *address;
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"%@",address); //可以正常访问到address,不用引入头文件即可
}
但是如果把 FirstObj 中的address声明为静态全局变量,那么在其他文件中即使通过extern 也不能访问到。
注意:在头文件中定义的全局静态变量,如果在不同的文件中引用的话,他会初始化多次,在不同文件中引用的该变量不是同一个变量,地址是不同的。
三、extern 关键字
extern 关键字只是用来获取值的,不要用来定义变量。
extern NSString *address = @"123"; //这样会有编译警告的
它的作用:声明一个外部变量,先在当前文件查找有没有全局变量,没有找到,才会去其他文件查找。
注意:extern不能和static组合使用,一个是外部链接,一个是内部链接,两者是冲突的