1. 程式人生 > >IOS const static extern 深度解析

IOS const static extern 深度解析

我想對於ios開發的人來講這3個關鍵字一定都很熟悉,但是你真的都明白了嗎?下面模擬一下面試。我們一層層的深入分析。

1.請你說一下const和巨集的區別

首先,很多字串我們都定義成巨集,但是蘋果推薦的是使用const。

區別:

1.編譯時刻:const是編譯階段,define是預編譯階段

2.編譯檢查:由於巨集是預編譯階段處理,巨集不做檢查,只是單純的替換。 const是會編譯檢查, 可以報編譯錯誤。

3.巨集的優勢:可以定義函式,方法。const不行

4.巨集的劣勢:大量巨集,會造成編譯時間久,每次都需要重新替換。

 

好了,記下來會繼續深入問你const

2.那你看這段程式碼給我說一下兩種寫法哪個會有問題

答案是兩種寫法都是對的。都是定義一個常量b,如果對b修改會引起報錯;

下面繼續:

int a = 10;
  
int *const p = &a; 
int const  *p = &a; 
       
*p = 20; 
p = &b;

說一下這兩種寫法有什麼區別:

如果const修飾的是p,那麼p的值是不能改變的,也就是p中存放的a的地址無法改變(p是int型別的指標變數)。但是*p是可以變化的,我們並沒有

用const去修飾*p,所以可以通過*p去改變a的值

如果const修飾的是*p,那麼*p的值是不能改變也,也就是p中存放的a的地址中的值無法改變,但是p的值是可以改變的(也就是p此時可以改變指向)

3.那你跟我說下static吧,static是做什麼用的。

static就是修飾變數的,可以延長區域性變數的生命週期,從棧區拿到全域性區。恭喜你,這樣答分數很低。面試官會給你幾個demo。看看你是否真的理解了static。其實static的作用是需要細分的。

 

  • 修飾區域性變數:

    1.延長區域性變數的生命週期,程式結束才會銷燬。

    2.區域性變數只會生成一份記憶體,只會初始化一次。

    3.改變區域性變數的作用域。

  • 修飾全域性變數

    1.只能在本檔案中訪問,修改全域性變數的作用域,生命週期不會改

    2.避免重複定義全域性變數

為了考察你的理解:會問你,那你說一下static在記憶體上怎麼處理的。比如我現在有一個類,類中用static定義一個區域性變數,每次執行這個static記憶體做了哪些事(從記憶體空間的角度)

-(void)method3:(NSMutableString *)str
{
    static int n = 1;
//    static等價語句
//    if (變數n沒有儲存空間)
//    {
//        給n分配儲存空間
//    }
    [str appendFormat:@"%d ", n];
    n++;
    
    g1 = 400;
}

答:如同註釋,將Int n 從棧區拿到全域性區,延長n的生命週期到程式結束。如果多次呼叫method3方法。都會判斷是否已經初始化了n,如果沒有初始化,開闢記憶體空間,如果已經分配了,就把全域性區的n,拿過來繼續使用。

應該怎麼理解呢。我們來看一下程式碼:

// static修飾全域性變數
static int age = 10;
- (void)test
{
    // static修飾區域性變數
    static int age = 0;
    age++;
    NSLog(@"%d",age);
}
- (void)viewDidLoad {
    [super viewDidLoad];   
    [self test];
    [self test];
    
    extern int age;
    NSLog(@"%d",age);
}

如果你回答很含糊,很簡單,面試官就會讓你看一段虛擬碼,來考察一下你是不是真的懂了。首先輸出結果是 1  , 2  ,10。這就考察了你是否真的理解static,首先,test裡面試區域性變數age。static的修飾只是延長了區域性變數的生命週期。從棧區拿到了全域性區。所以第一次輸出1,第二次輸出2,每次+1。最後一個行輸出考察了extern,其實就是獲取本檔案的全域性變數,後面我們會細說。所以這裡全域性變數定義了10,就輸出10,而沒有輸出區域性變數2.

好了,繼續深入問:

.m中

const NSString *HSCoder = @"hello word";

另一個類的.m中

    extern NSString *HSCoder;
    NSLog(@"%@",HSCoder);

問你可以輸出嗎?hello word嗎?

.m中

NSString  *const nameKey = @"name"

.h中

extern NSString * const nameKey;

另一個類的.m中

 NSLog(@"%@",nameKey);

問你可以輸出name嗎?

答案是都可以。這就是extern的用法

 

  • extern作用:
    • 只是用來獲取全域性變數(包括全域性靜態變數)的值,不能用於定義變數
  • extern工作原理:
    • 先在當前檔案查詢有沒有全域性變數,沒有找到,才會去其他檔案查詢。

好了,繼續問。如果將全域性常量,加上static修飾,上面的程式碼會輸出什麼

static const NSString *HSCoder = @"hello word";

這裡又考到了static的作用,千萬不要想成什麼延長生命週期,繼續累加等等。。。注意到static的作用分為兩方面。這裡問的是修飾全域性的。不改變生命週期,單純的修改作用域。讓這個常量只能在當前.m使用。所以,這段程式碼編譯會報錯