窥探iOS底层实现--OC对象的本质(一) - 掘金objective-c
窥探iOS底层实现--OC对象的本质(二) - 掘金swift
窥探iOS底层实现--OC对象的分类:instance、class、meta-calss对象的isa和superclass - 掘金安全
1.extern
全局变量extern,也称之为外部变量,是在方法外部定义的变量。它不属于那个方法,而是属于整个源程序。做用因而整个程序。若是全局变量和局部变量重名,则在局部变量做用域内,全局变量被屏蔽,不起做用post
///> DDExtern.h
#import <Foundation/Foundation.h>
NSString *flag = @"DDExtension";
@interface DDExtern : NSObject
@end
复制代码
定义了一个字符串 flagui
///> main.m
#import <Foundation/Foundation.h>
int main(int argc, const char \* argv\[\]) {
extern NSString *flag;
NSLog(@"%@",flag);
return 0;
}
复制代码
打印结果:DDExtension
复制代码
从例子中能够看出,main.m无需导入JJExtern的头文件,直接在NSString *flag前面加上extern关键字就能够取到JJExtern的flag值。 须要注意的是,extern修饰的变量名必须是和Extern下的变量名一致,即都为flag,不然会都提示找不到。 还须要注意extern修饰的变量是没有真的内存的。spa
既然只须要extern就能获得并修改其余文件的变量,这样不是很不安全?由于随时都会被人改掉,怎么办??3d
使用接下来所讲的 static关键字修饰变量,那么该变量就只能在本文件中修改,其余文件没法使用extern获取变量指针
2.static
static 既能够修饰全局变量,又能够修饰局部变量。code
修饰全局变量
使用以前的例子,在JJExtern的 NSString *flag = @"JJExtension"; 前面加 static,以下
///> JJExtern.h
#import <Foundation/Foundation.h>
static NSString *flag = @"DDExtension";
@interface JJExtern : NSObject
@end
复制代码
再次运行main函数 编译会报错
修饰局部变量:
代码:
///> main.m
void test() {
static int a = 0;
a++;
NSLog(@"a = %d", a);
}
int main(int argc, const char \* argv\[\]) {
@autoreleasepool {
for (int i = 0; i<3; i++) {
test();
}
}
return 0;
}
/** 输出结果: * 2018-12-05 19:20:55.494405+0800 tesy[11959:2261816] a = 1 * 2018-12-05 19:20:55.499893+0800 tesy[11959:2261816] a = 2 * 2018-12-05 19:20:55.505727+0800 tesy[11959:2261816] a = 3 */
复制代码
修饰局部变量时,做用域仅限于test函数的大括号内,其余地方都不可使用。test这个函数中若是不添加 static,那么a打印出来永远都是1,由于在运行完此段函数 局部变量a就会被释放。从新执行函数时a++为0+1.
加上static以后的含义就改变了,结果为1,2,3。由于被static修饰的变量只会初始化一次,永远都只有一分内存,因此当第一次调用test函数时a就已经被初始化了,a有一个内存空间而且值为0,第二次调用test函数因为a被static修饰,因此不会再初始化新的值,它会拿到以前的那分内存进行a++操做,就会变成1,以此类推。
3. const
const的做用和宏相似,苹果不推荐使用宏定义,推荐使用const,因此在swift中苹果抛弃了宏的使用。
const 和 宏的区别
\ | 宏 | const |
---|---|---|
编译时刻 | 预编译(在编译前处理) | 编译阶段 |
编译检查 | 不作检查,不会报编译错误,单纯替换功能,用宏定义的函数会报参数类型错误 | 会作编译检查,会报编译错误 |
宏的好处 | 宏能定义一些函数、方法 例如RGB函数 | 不能 |
宏的坏处 | 使用大量的宏,容易形成编译时间久每次都须要从新替换 | 1.0.2 -> 1.0.4 |
三段代码理解const
int x = 1;
int y = 2;
const int *px = &x; // 让指针px指向变量x(此时const右边是*p)
px = &y;// 改变指针px的指向,使其指向变量y
*px = 3; // 改变px指向的变量x的值,出错:Read-only variable is not assignable
复制代码
int x = 1;
int y = 2;
const int *px = &x; // 让指针px指向变量x(此时const右边是*p)
px = &y; // 改变指针px的指向,使其指向变量y
*px = 3; // 改变px指向的变量x的值,出错:Read-only variable is not assignable
复制代码
int x = 1;
int y = 2;
const int *px = &x;// 让指针px指向变量x(此时const右边是*p)
px = &y; // 改变指针px的指向,使其指向变量y
*px = 3; // 改变px指向的变量x的值,出错:Read-only variable is not assignable
复制代码
上面的三段代码处理的是基本数据类型,咱们知道OC语言是C语言的超集,因此上面部分基本数据类型的处理OC与C同样。 可是咱们知道OC是C语言的超集,OC中还有NSString等的数据类型,它们的本质是个结构体,因此在处理指针方面与基本数据类型不一样
代码以下:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
NSString const *name = @"milo";// const修饰*name
NSLog(@"%@",name);// 打印结果“milo”
name = @"vicky";// 在oc中NSString等类的值不是经过*name访问的,而是经过name访问的,这就是和c语言的指针的区别,但仍是遵循const右边是谁,谁就只可读的原则。
NSLog(@"%@",name);// 打印结果“vicky”
}
复制代码
objective-c语言代码
- (void)viewDidLoad {
[super viewDidLoad];
// 定义变量
int a = 1;
// 容许修改值
a = 20;
// const两种用法
// const:修饰基本变量p
// 这两种写法是同样的,const只修饰右边的基本变量b
const int b = 20; // b:只读变量
int const b = 20; // b:只读变量
b = 1; // 不容许修改值
// const:修饰指针变量\*p,带\*的变量,就是指针变量.
// 定义一个指向int类型的指针变量,指向a的地址
int *p = &a;
int c = 10;
p = &c;
// 容许修改p指向的地址,
// 容许修改p访问内存空间的值
*p = 20;
// const修饰指针变量访问的内存空间,修饰的是右边*p1,
// 两种方式同样
const int *p1; // *p1:常量 p1:变量
int const *p1; // *p1:常量 p1:变量
// const修饰指针变量p1
int * const p1; // *p1:变量 p1:常量
// 第一个const修饰*p1 第二个const修饰 p1
// 两种方式同样
const int * const p1; // *p1:常量 p1:常量
int const * const p1; // *p1:常量 p1:常量
}
复制代码
4. static、const结合使用
一个文件中
常用的字符串常量,可使用static与const组合///> 开发中经常使用static修饰全局变量,只改变做用域
///> 为何要改变全局变量做用域,防止重复声明全局变量。
///> 开发中声明的全局变量,有些不但愿外界改动,只容许读取。
///> 好比一个基本数据类型不但愿别人改动
///> 声明一个静态的全局只读常量
static const int a = 20;
///> staic和const联合的做用:声明一个静态的全局只读常量
///> iOS中staic和const经常使用使用场景,是用来代替宏,把一个常用的字符串常量,定义成静态全局只读变量.
///> 开发中常常拿到key修改值,所以用const修饰key,表示key只读,不容许修改。
static NSString * const key = @"name";
///> 若是 const修饰 *key1,表示*key1只读,key1仍是能改变。
static NSString const *key1 = @"name";
复制代码
5. extern与const联合使用
多个文件中
常用的同一个字符串常量,可使用extern与const组合。///> In the header file
extern NSString *const EOCStringConstant;
///> In the implementation file
NSString *const EOCStringConstant = @"VALUE";
复制代码