窺探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函數 編譯會報錯
因此只要在全局變量前加static,那麼這個全局變量的做用域就會縮小到當前文件,外界就不能訪問了修飾局部變量:
代碼:
///> 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";
複製代碼