去阿里面試被問到了好多基本功和底層知識(shí),由于沒有總結(jié)過萝风,導(dǎo)致有很多用過的東西并不知道怎么表達(dá)嘀掸,遭到了無情的鄙視;決定總結(jié)一些知識(shí)點(diǎn)闹丐,激勵(lì)自己一下横殴!
先從最基本的寫起:先寫幾個(gè)修飾關(guān)鍵字 const、static卿拴、extern.
一衫仑、const:: 被const修飾的變量是只讀的(變量->只讀變量).
先從最基礎(chǔ)的開始
定義變量
int a = 1;
a = 20;// 允許修改值
然后開始進(jìn)入const
const兩種用法
1、const:修飾基本變量p
const int b = 20; // b:只讀變量
int const b = 20; // b:只讀變量
b = 1; // 會(huì)報(bào)錯(cuò)// 不允許修改值
2堕花、const:修飾指針類型*p
定義一個(gè)指向int類型的指針文狱,指向a的地址
int a = 20;
int *p = &a;
NSLog(@"p == %p---&a == %p",p,&a);
int c = 10;
p = &c;
NSLog(@"p == %p---*p == %d",p,*p);
int d = 11;
*p = d;
NSLog(@"p == %p---*p == %d",p,*p);
//打印結(jié)果
2019-07-11 09:45:32.867368+0800 Runtime理解[44662:1691119] p == 0x7ffeefb433ac---*p == 20
2019-07-11 09:45:32.867518+0800 Runtime理解[44662:1691119] p == 0x7ffeefb4339c---*p == 10
// 允許修改p指向的地址
2019-07-11 09:45:32.867637+0800 Runtime理解[44662:1691119] p == 0x7ffeefb4339c---*p == 11
// 允許修改p訪問內(nèi)存空間的值
const修飾指針變量訪問的內(nèi)存空間,修飾的是右邊*p1缘挽,
int a = 20;
const int *p = &a;
NSLog(@"p == %p---*p == %d",p,*p);
int c =10;
p = &c;
NSLog(@"p == %p---*p == %d",p,*p);
//打印結(jié)果
2019-07-11 10:15:54.968002+0800 Runtime理解[45151:1709783] p == 0x7ffee3f193ac---*p == 20
2019-07-11 10:15:54.968132+0800 Runtime理解[45151:1709783] p == 0x7ffee3f1939c---*p == 10
// 允許修改p指向的地址
int d = 11;
*p = d;//報(bào)錯(cuò)瞄崇,Read-only variable is not assignable(只讀變量不可賦值)
// 不允許修改p訪問內(nèi)存空間的值
int a = 20;
const *p = &a;
NSLog(@"p == %p---*p == %d",p,*p);
int c =10;
p = &c;
NSLog(@"p == %p---*p == %d",p,*p);
//打印結(jié)果
2019-07-11 10:15:54.968002+0800 Runtime理解[45151:1709783] p == 0x7ffee3f193ac---*p == 20
2019-07-11 10:15:54.968132+0800 Runtime理解[45151:1709783] p == 0x7ffee3f1939c---*p == 10
// 允許修改p指向的地址
int d = 11;
*p = d;//報(bào)錯(cuò),Read-only variable is not assignable(只讀變量不可賦值)
// 不允許修改p訪問內(nèi)存空間的值
int a = 20;
int const *p = &a;
NSLog(@"p == %p---*p == %d",p,*p);
int c =10;
p = &c;
NSLog(@"p == %p---*p == %d",p,*p);
//打印結(jié)果
2019-07-11 10:15:54.968002+0800 Runtime理解[45151:1709783] p == 0x7ffee3f193ac---*p == 20
2019-07-11 10:15:54.968132+0800 Runtime理解[45151:1709783] p == 0x7ffee3f1939c---*p == 10
// 允許修改p指向的地址
int d = 11;
*p = d;//報(bào)錯(cuò)壕曼,Read-only variable is not assignable(只讀變量不可賦值)
// 不允許修改p訪問內(nèi)存空間的值
總結(jié):const int *p 作用等同于 int const *p
*p 是常量 p是變量
int a = 20;
int * const p = &a;
NSLog(@"p == %p---*p == %d",p,*p);
int c =10;
p = &c; //報(bào)錯(cuò)苏研,Read-only variable is not assignable(只讀變量不可賦值)
// 不允許修改p指向的地址
int d = 11;
*p = d;
NSLog(@"p == %p---*p == %d",p,*p);
// 打印結(jié)果
2019-07-11 10:50:44.694506+0800 Runtime理解[45665:1731013] p == 0x7ffee8f413ac---*p == 20
2019-07-11 10:50:44.694684+0800 Runtime理解[45665:1731013] p == 0x7ffee8f413ac---*p == 11
// 允許修改p訪問內(nèi)存空間的值
總結(jié): int *const p *p是變量 p是常量;
通過以上代碼總結(jié):const修飾的緊右邊的為常量腮郊,在此就不一一驗(yàn)證摹蘑,有興趣的可以自己寫代碼驗(yàn)證一下;
const int *p // *p:常量 p:變量
int const *p // *p:常量 p:變量
int *const p // *p:變量 p:常量
const int * const p // *p:常量 p:常量
int const * const p // *p:常量 p:常量
下面來試驗(yàn)一下const最常用的方法:修飾NSString轧飞,廢話少說衅鹿,上代碼:
NSString * const str1=@"sdh";
str1 = @"123" //報(bào)錯(cuò)
//因?yàn)镹SString是不可變字符串:指針指向內(nèi)存的內(nèi)容是不允許改變的撒踪,因?yàn)閏onst修飾的是指針 str1:指針不允許指向其他內(nèi)存;
//所以不可以修改指針指向的原內(nèi)存中的內(nèi)容大渤,指針不可以指向其他的內(nèi)存
NSString const *str2 = @"sdh";
str2 = @"123"; //不報(bào)錯(cuò)
//因?yàn)镹SString是不可變字符串:指針指向內(nèi)存的內(nèi)容是不允許改變的制妄,因?yàn)閏onst修飾的是指針 *str2:指針指向內(nèi)存的內(nèi)容不允許改變,所以 *str2 是常量 但str2是變量指針可以指向一天內(nèi)存;
//所以不可以修改指針指向的原內(nèi)存中的內(nèi)容泵三,指針可以指向其他的內(nèi)存
NSMutableString *const var1 =[NSMutableString string];
NSMutableString *var2 = [NSMutableString stringWithFormat:@"%@",@"123"];
var1 = var2; //報(bào)錯(cuò) 因?yàn)閏onst修飾的是指針 var1:指針不允許指向其他內(nèi)存耕捞;
[var1 appendString:@"123"]; //不報(bào)錯(cuò) 因?yàn)镹SMutableString是可變字符串:指針指向內(nèi)存的內(nèi)容是允許改變的
//所以可以修改指針指向的原內(nèi)存中的內(nèi)容,指針不可以指向其他的內(nèi)存
NSMutableString const *var3 =[NSMutableString string];
var3 = var2; //不報(bào)錯(cuò) 因?yàn)閏onst修飾的是指針 *var3 所以var3是變量烫幕,指針可以指向其他內(nèi)存地址
[var3 appendString:@"123456"]; //不報(bào)錯(cuò) 因?yàn)関ar3是可變字符串指針指向的原內(nèi)存中的內(nèi)容可以改變
//所以可以修改指針指向的原內(nèi)存中的內(nèi)容砸脊,常量指針可以指向其他的內(nèi)存
NSLog(@"str1 = %@ -- str2 = %@ -- var1 = %@ -- var2 = %@",str1,str2,var1,var2);
//打印結(jié)果
2019-07-11 11:28:43.957979+0800 Runtime理解[46292:1755776] str1 = sdh -- str2 = 123 -- var1 = 123 -- var2 = sdh123456
const修飾字符串總結(jié):
NSString *const str1
不可以修改指針指向的原內(nèi)存中的內(nèi)容,指針不可以指向其他的內(nèi)存
NSString const *str2
不可以修改指針指向的原內(nèi)存中的內(nèi)容纬霞,指針可以指向其他的內(nèi)存
NSMutableString const *var1
可以修改指針指向的原內(nèi)存中的內(nèi)容凌埂,指針可以指向其他的內(nèi)存
NSMutableString *const var2
可以修改指針指向的原內(nèi)存中的內(nèi)容,指針不可以指向其他的內(nèi)存
const用法總結(jié)道這里诗芜。
二瞳抓、static和extern簡(jiǎn)單使用
"static作用":
1、修飾局部變量:
1)延長(zhǎng)局部變量的生命周期,程序結(jié)束才會(huì)銷毀伏恐。
2)局部變量只會(huì)生成一份內(nèi)存,只會(huì)初始化一次孩哑。
3)Static關(guān)鍵字不可以改變局部變量的作用域。
@implementation Person
-(instancetype)init{
self = [super init];
if (self) {
[self conlogAge];
[self conlogAge];
}
return self;
}
-(void)conlogAge{
static NSInteger age = 18;
age ++;
NSLog(@"%ld",age);
}
#import "Person.h"
@interface ConstStaticViewController ()
@end
@implementation ConstStaticViewController
- (void)viewDidLoad {
[super viewDidLoad];
Person *per = [Person new];
Person *per2 = [Person new];
}
//打印輸出
//2019-07-11 15:19:25.617612+0800 Runtime理解[49598:1888382] 19
//2019-07-11 15:19:25.617712+0800 Runtime理解[49598:1888382] 20
//2019-07-11 15:19:25.617800+0800 Runtime理解[49598:1888382] 21
//2019-07-11 15:19:25.617892+0800 Runtime理解[49598:1888382] 22
注意:ConstStaticViewController是二級(jí)頁(yè)面翠桦,我們返回到一級(jí)頁(yè)面横蜒,該頁(yè)面銷毀,在重新創(chuàng)建改頁(yè)面销凑,viewDidLoad會(huì)重新執(zhí)行一次丛晌,我們?cè)诳创蛴?shù)據(jù):
2019-07-11 15:42:11.181260+0800 Runtime理解[50022:1905671] 19
2019-07-11 15:42:11.181433+0800 Runtime理解[50022:1905671] 20
2019-07-11 15:42:11.181541+0800 Runtime理解[50022:1905671] 21
2019-07-11 15:42:11.181711+0800 Runtime理解[50022:1905671] 22
2019-07-11 15:42:14.761006+0800 Runtime理解[50022:1905671] 23
2019-07-11 15:42:14.761159+0800 Runtime理解[50022:1905671] 24
2019-07-11 15:42:14.761285+0800 Runtime理解[50022:1905671] 25
2019-07-11 15:42:14.761378+0800 Runtime理解[50022:1905671] 26
說明:
1、age這個(gè)變量并未因持有他的對(duì)象的銷毀兒銷毀斗幼,局部變量的生命周期被延長(zhǎng)
2澎蛛、而且, [self conlogAge]函數(shù)被調(diào)用多次蜕窿,age這個(gè)變量并未重新初始化谋逻,而是跳過初始化,繼續(xù)進(jìn)行 ++操作桐经,所以:局部變量只會(huì)生成一份內(nèi)存,只會(huì)初始化一次毁兆。
-(void)conlogAge{
static NSInteger age = 18;
age ++;
NSLog(@"%ld",age);
}
-(void)showAge{
age++;//直接報(bào)錯(cuò)
extern NSInteger age; //編譯時(shí)報(bào)錯(cuò)
NSLog(@"%ld",age);
}
3、被static修飾過的變量阴挣,在其他作用域是不能訪問的气堕。
2、static修飾全局變量
1)只能在本文件中訪問,修改全局變量的作用域,生命周期不會(huì)改
2)避免重復(fù)定義全局變量
NSString *allChange = @"allChange";//全局變量,本文件直接用送巡,其他文件借助extern調(diào)用
static NSString *changes =@"change";//全局變量,本文件直接用盒卸,其他文件借助不能調(diào)用,用extern調(diào)用骗爆,會(huì)報(bào)錯(cuò)
三、const蔽介、static配合使用
開發(fā)時(shí)常用的寫法摘投,用const、和static配合使用來代替宏的部分功能(#define)
一虹蓄、const與宏的區(qū)別(面試題):
- "const簡(jiǎn)介":之前常用的字符串常量犀呼,一般是抽成宏,但是蘋果不推薦我們抽成宏薇组,推薦我們使用const常量外臂。
- "執(zhí)行時(shí)刻":宏是預(yù)編譯(編譯之前處理),const是編譯階段律胀。
- "編譯檢查":宏不做檢查宋光,不會(huì)報(bào)編譯錯(cuò)誤,只是替換炭菌,const會(huì)編譯檢查罪佳,會(huì)報(bào)編譯錯(cuò)誤。
- "宏的好處":宏能定義一些函數(shù)黑低,方法赘艳。 const不能。
- "宏的壞處":使用大量宏克握,容易造成預(yù)編譯時(shí)間久蕾管。
#define CHANGE @"change";
static NSString *const changes =@"change";
雖然測(cè)試過,及時(shí)用相當(dāng)數(shù)量的宏編譯時(shí)間并不會(huì)差很多菩暗,但是娇掏,我們還是要按照蘋果的推薦來的好,用第二個(gè)表示方法勋眯。
四婴梧、extern使用
"extern作用":只是用來獲取全局變量(包括全局靜態(tài)變量)的值,不能用于定義變量客蹋。
"extern工作原理":先在當(dāng)前文件查找有沒有全局變量塞蹭,沒有找到,才會(huì)去其他文件查找讶坯。
廢話補(bǔ)多說:代碼解釋
#import "SLStaticDemo.h"
NSInteger age = 10;
@implementation SLStaticDemo
@end
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
extern NSInteger age;
NSLog(@"age = %ld", (long)age);
age += 10;
NSLog(@"age = %ld", (long)age);
}
@end
打印結(jié)果:
從輸出結(jié)果 age = 10 我們可以看到即便我們?cè)赩iewController.m中并沒有import SLStaticDemo.h也能得到SLStaticDemo中定義的age變量番电,這就是extern關(guān)鍵字的功勞(extern可以訪問全局變量);
注:這里理解起來很簡(jiǎn)單,懶得自己寫了漱办,參照的大神的代碼这刷,網(wǎng)址:http://www.reibang.com/p/9c09989b6862
好,用了將近一天的時(shí)間娩井,把這三個(gè)基本的關(guān)鍵字理清了暇屋,可能有寫啰嗦,希望大家選擇性參考洞辣。