3.1 OC特性之 內存五大區域


此篇為針對Objective-c語言入門的基礎知識,為了能讓大家更清楚的理解,此整理中編寫了許多的代碼案例和部分截圖,如有錯誤之處,望指正,願與您相互交流學習,共同進步!---"會飛的猴子_阿新" (同時還要向刀哥致敬)

本篇目標是: 理解內存五大區域及各自的職責

目錄結構

00.簡述

程序要想執行,第一步就需要 被加載到內存中
內存五大區域: 棧區,堆區,BSS段(靜態區),常量區(數據段),代碼段.

  1. 棧區: 局部變量和方法實參
  2. 堆區:OC中使用new方法創建的對象,被創建對象的所有成員變量保存在堆區中.
  3. BSS段(也叫靜態區):
    教科書:未被初始化的全局變量和靜態變量.
    Xcode8中: 全局變量和靜態變量,不管有沒有被初始化,都存放在BSS段中.驗證見本篇中的案例.
  4. 常量區(也叫數據段):
    教科書: 存儲已經初始化的全局變量,靜態變量,常量.
    xcode8: 存儲常量
  5. 代碼段: 程序的代碼.
    內存五大區域01

01. 分配和釋放(面試常被問到)

  • 棧區 (stack [stæk]): 由編譯器自動分配釋放

    1. 局部變量是保存在棧區的
    2. 方法調用的實參也是保存在棧區的
  • 堆區 (heap [hiːp]): 由程序員分配釋放,若程序員不釋放,會出現內存泄漏

    1. 賦值語句右側 使用 new 方法創建的對象
    2. 被創建對象的所有 成員變量
  • BSS 段 : 程序結束后由系統釋放

  • 數據段 : 程序結束后由系統釋放

  • 代碼段:程序結束后由系統釋放

    程序 編譯鏈接 后的二進制可執行代碼

02.棧區和堆區

int main(int argc, const char * argv[]) {

    // 局部變量是保存在棧區的
    // 棧區變量出了作用域之后,就會被銷毀
    NSInteger i = 10;

    NSLog(@"%zd", i);

    // 局部變量是保存在棧區的
    // 賦值語句右側,使用 new 方法創建的對象是保存在堆區的
    // xinge 變量中,記錄的是堆區的地址
    // 在 OC 中,有一個內存管理機制,叫做 `ARC`,可以自動管理 OC 代碼創建對象的生命周期
    // 因此,在開發 OC 程序的時候,程序員通常不需要考慮內存釋放的工作
    LJXPerson *xinge = [LJXPerson new];
    NSLog(@"%@", xinge);
    return 0;
}

10
<LJXPerson: 0x100404b70>

2.1 棧區

棧區 (stack [stæk]) : 由編譯器自動分配釋放

2.1.1 棧區中的保存(棧區的職責/存儲的內容)

  • 局部變量
  • 方法實參(eg:在main函數中,調用方法,方法中的實參)

2.1.2 棧區的特點

  • 存儲空間有限 . iphone的棧區大小只有512k(默認) ,非常有限
  • 連續性 . 棧區的地址是連續的
部分代碼:
#import <Foundation/Foundation.h>
#import "LJXPerson.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSInteger i = 10;
        NSLog(@"i 的棧區地址是 %p", &i);
        
        NSInteger j = 10;
        NSLog(@"j 的棧區地址是 %p", &j);
        
        // xiaoming 變量中,存儲的是 LJXPerson 
        對象的內存地址(堆區的內存地址)
        LJXPerson *xinge = [LJXPerson new];
        NSLog(@"xinge 的棧區地址是 %p", &xinge);
        
        double height = 10;
        NSLog(@"height 的棧區地址是 %p", &height);
        .......

i 的棧區地址是 0x7fff5fbff768
j 的棧區地址是 0x7fff5fbff760
xinge 的棧區地址是 0x7fff5fbff758
height 的棧區地址是 0x7fff5fbff750

  • 地址分配從大到小. 棧區地址按照分配的順序,由大到小順序排列
  • 訪問速度快.
  • 系統管理. (棧區的內存由系統管理)

2.1.3 其他

如果在程序中調用方法,會開啟一個  " 棧幀 ".(這個棧幀可以理解為也是一塊連續的區域)

棧幀的地址與之前的局部變量的地址不是連續的棧幀中記錄實參地址,
以及方法內部的局部變量方法執行完畢后,棧幀銷毀(彈棧)   

<<<這樣每次執行完畢后,都彈棧釋放內存,這樣就會始終保證棧區占用的內存不會特別大>>

so-課外話->我們在開發的時候,如果每個方法都寫的很短,同時每個方法聲明的變量都很少.
這樣做一定會節約內存


見圖知意

添加 "在一個函數/方法中"

即在一個函數/方法中最多可定義65536,--->因為"每次"執行完"一個"方法之后就會彈棧釋放內存

棧的概念:  后進先出/  先進后出

見圖知意:

NSLog(@"NSInteger 變量占用的字節數 %tu", sizeof(NSInteger));
        NSLog(@"double 變量占用的字節數 %tu", sizeof(double));
        NSLog(@"xinge 變量占用的字節數 %tu", sizeof(xinge));
        
        // 提示:棧區中,只適合存儲非常小的數據
        NSLog(@"在 iPhone 中,最多可以在一個函數/方法中定義 %zd 個局部變量", 512 * 1024 / 8);
        
        // 測試方法調用時,實參在棧區的存儲情況
        [xinge sumWithNum1:i andNum2:j];        

總結:  調用方法時棧區的工作原理
        * 開啟棧幀
        * 保存實參
        * 保存局部變量
        * 方法完成后彈棧,銷毀棧幀,釋放空間

2.2 堆區

堆區 (heap [hiːp]): 由程序員分配釋放,若程序員不釋放,會出現內存泄漏

2.2.1 堆區中保存:

  • 使用 new 方法創建的對象保存在堆區
  • 被創建對象的所有成員變量保存在堆區中
堆區的職責是"解決棧區空間有限的問題"

* OC 使用`new`方法創建的對象
--->{由於 **ARC 管理機制**,OC 程序員通常不需要考慮對象的釋放.}
  (在 OC 中,有一個內存管理機制,叫做 ARC(自動引用計數)
  可以自動管理 OC 代碼創建對象的生命周期)
* C 語言使用 malloc、calloc、realloc 函數分配的空間,需要使用 free 函數釋放

顧: 在開發 OC 程序的時候,程序員通常不需要考慮內存釋放的工作
但是:如果在 OC 的代碼中,如果使用到 C 語言分配空間的函數,則需要考慮釋放內存

1. 堆區的大小由系統決定,包括:系統內存/磁盤交換空間...
2. 系統使用`鏈表`來管理堆區中的內存分配情況
3. {**程序員只需要負責堆區中內存的分配和釋放工作**}

2.2.2能夠說出堆區的特點

  1. 所有程序共享
  2. 存儲大數據
  3. 程序員管理: 堆區的內存需要程序員管理
  4. 不連續: 堆區的地址是不連續的
  5. 速度沒有棧區快: 堆區的訪問速度沒有棧區快,因為我們要訪問堆區中創建對象的屬性, 必須先需要通過變量找到棧區的地址,再通過地址定位到到堆區中的某一個位置, 只有找個這個位置之后,我們才可以訪問到存儲到這個對象中屬性對應的數值.由於有了 這個地址尋找的過程,所有速度沒有棧區的快.

0.3 全局變量、靜態變量和常量

3.1 全局變量/靜態變量/常量保存的內存區域

開發要讓 變化控制在有限的范圍內

3.1.1 教科書中 全局變量 和 靜態變量 的存儲區域

  1. 有初始值的 全局變量 和 靜態變量 保存在 數據段(常量區)
  2. 沒有初始值的 全局變量 和 靜態變量 保存在 BSS 段(靜態區)
    當給 全局變量 或 靜態變量 設置初始值后,會被移動到 數據段(常量區)

3.1.2 Xcode 8 中 全局變量 和 靜態變量 的存儲區域

  1. 無論是否設置初始值全局變量 和 靜態變量 都保存在 BSS 段(靜態區)

  2. 常量 存儲在 數據段(常量區)


注意:(全局/靜態變量,常量)教科書與xcode8驗證有點差別

(1) xcode8 "全局變量"實際存儲區域案例驗證:

案例代碼:

#import <Foundation/Foundation.h>

NSInteger num1 = 10;  //定義第一個全局變量  並且初始化
NSInteger num2;      //定義第二個全局變量   沒有初始化

int main(int argc, const char * argv[]) {
    @autoreleasepool {  
        // 提示:在 Xcode 8 中,全局變量無論是否初始化,地址保持不變
        NSLog(@"第1個全局變量的地址%p", &num1);  //第1個全局變量的地址0x100001188
        NSLog(@"第2個全局變量的地址%p", &num2);  //第2個全局變量的地址0x100001190
        num2=100;
       NSLog(@"第2個全局變量的地址%p(初始化后的)", &num2);
        //第2個全局變量的地址0x100001190(初始化后的)   
    }
    return 0;
}


第1個全局變量的地址0x100001188
第2個全局變量的地址0x100001190
第2個全局變量的地址0x100001190(初始化后的)
Program ended with exit code: 0

可見1:地址從小到大是連續的

可見2:

在 Xcode 8 中,全局變量無論是否初始化,地址保持不變


(2)xcode8 "靜態變量"實際存儲區域案例驗證:

#import <Foundation/Foundation.h>

static NSInteger num1 = 10;  //定義第一個全局變量  並且初始化
static NSInteger num2;      //定義第二個全局變量   沒有初始化

static NSInteger sNum1 = 10;  //定義第一個靜態的全局變量  並且初始化
static NSInteger sNum2;      //定義第二個靜態的全局變量   沒有初始化

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        // 提示:在 Xcode 8 中,全局變量無論是否初始化,地址保持不變
        NSLog(@"第1個全局變量的地址%p", &num1);  //第1個全局變量的地址0x1000011f8
        NSLog(@"第2個全局變量的地址%p", &num2);  //第2個全局變量的地址0x100001208
        num2=100;
        NSLog(@"第2個全局變量的地址%p(初始化后的)", &num2);//第2個全局變量的地址0x100001208(初始化后的)
        NSLog(@"##############################################");
        NSLog(@"第1個靜態的全局變量的地址%p", &sNum1);  //第1個靜態的全局變量的地址0x100001200
        NSLog(@"第2個靜態的全局變量的地址%p", &sNum2);  //第2個靜態的全局變量的地址0x100001210
        sNum2=100;
        NSLog(@"第2個靜態的全局變量的地址%p(初始化后的)", &sNum2);//第2個靜態的全局變量的地址0x100001210(初始化后的)
    }
    return 0;
    }    

第1個全局變量的地址0x1000011f8
第2個全局變量的地址0x100001208
第2個全局變量的地址0x100001208(初始化后的)
################################
第1個靜態的全局變量的地址0x100001200
第2個靜態的全局變量的地址0x100001210
第2個靜態的全局變量的地址0x100001210(初始化后的)
Program ended with exit code: 0

可見1. 靜態變量的初始化前后地址也是不變的

可見2. 靜態變量和全局變量是交叉保存的

so-->面試注意:
   ---->在xcode 8中, 靜態變量和全局變量保存在同一個區域
   ---->在xcode 8中, 靜態變量和全局變量都保存在BSS段中.
   跟我們教課書上是有區別的,
   so-->當面試中遇到這個問題時,我們可以這樣回答:
        在教課書中:BSS段存放的是未被初始化的全局變量和靜態變量,
        但是我們通過xcode8 驗證后,他們不管是全局變量
        還是靜態變量都存儲在BSS段中.
        

(3)xcode8 "常量"實際存儲區域案例驗證:

#import <Foundation/Foundation.h>

       NSInteger num1 = 10;
       NSInteger num2;

static NSInteger sNum1 = 10;
static NSInteger sNum2;
const NSInteger cNum = 10000;//定義一個常量

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"第1個全局變量的地址%p", &num1);
        NSLog(@"第2個全局變量的地址%p", &num2);
        num2=100;
        NSLog(@"第2個全局變量的地址%p(初始化后的)", &num2);
        NSLog(@"##############################################");
        NSLog(@"第1個靜態的全局變量的地址%p", &sNum1);
        NSLog(@"第2個靜態的全局變量的地址%p", &sNum2);
        sNum2=100;
        NSLog(@"第2個靜態的全局變量的地址%p(初始化后的)", &sNum2);
        //第2個靜態的全局變量的地址0x100001230(初始化后的)
        NSLog(@"##############################################");
        NSLog(@"第1個常量的地址%p", &cNum); 
        //第1個常量的地址0x100000e88
    }
    return 0;
}

第1個全局變量的地址0x100001218
第2個全局變量的地址0x100001228
第2個全局變量的地址0x100001228(初始化后的)
#################
第1個靜態的全局變量的地址0x100001220
第2個靜態的全局變量的地址0x100001230
第2個靜態的全局變量的地址0x100001230(初始化后的)
##################
第1個常量的地址0x100000e88
Program ended with exit code: 0

常量存儲演示:面試萬一遇到,可演示一下,解釋與科普書上的不同

可見: 全局變量和靜態變量  跟常量放在不同的區域中,常量存放在常量區(或叫數據段).
*     教科書:數據段(常量區)用來存儲已經初始化的全局變量,靜態變量,常量.
*     xcode8:中數據段(常量區)存放的是常量.

3.2 BSS段(靜態區)

存儲的內容: (前面已經案例驗證過了):
1. 教科書: 存儲未初始化的 全局變量 和 靜態變量
2. Xcode 8驗證: 不管有沒有初始化均存儲 全局變量 和 靜態變量.

3.3 數據段(常量區)

存儲的內容: (前面已經案例驗證過了):

  1. 教科書 :存儲已經初始化的 全局變量、靜態變量、常量

  2. Xcode 8驗證 :不管有沒有初始化均存儲 常量.

3.4 全局變量與全局靜態變量的區別

  1. 若程序只有一個文件全局變量全局靜態變量沒有區別 (程序中只有一個文件,幾乎是不存在的,因為通常一個類就對應2個文件.)
  2. 若程序由多個文件構成時,全局變量全局靜態變量 不同:

  • 全局靜態變量 通常在定義該變量的文件內部使用 注意:

注意:

1.為什么OC中幾乎不使用 全局變量?
1. 因為程序的任何一個位置都可以對 全局變量 進行修改
2. 一旦程序出現由全局變量產生的錯誤,不好排查錯誤
3. 使用全局變量不是一個好習慣
[我的理解:因為當我們開發時文件有很多,但是又不能把全局變量定義到頭文件中
(如果定義在頭文件中,當別的類引入該頭文件后,相當於在兩個類中都低定義了該全局變量,
會出現重復定義),所有幾乎不使用.]
2.不能把 全局變量 定義在頭文件中

(我的理解:如果定義在頭文件中,當別的類引入該頭文件后,相當於在兩個類中都定義了該全局變量,會出現重復定義)

3.在程序開發時,全局變量 和 靜態變量 都不能重名

(我的理解:當跟別的變量重名時,會被重名的變量修改.)

4.靜態變量 的修改通常只是在 定義當前靜態變量的文件 內部進行

外部即使修改,但是由於地址不同,也不會影響到 定義靜態變量文件 內部的數值變化
一旦程序因為 靜態變量 產生錯誤,只需要在當前文件中,檢查一下修改 靜態變量 的代碼即可,排查錯誤難度相對降低

提示:在程序開發時,如果要使用全局的變量,應該在 .m 中定義一個全局的靜態變量,而不要把該變量暴露在頭文件中-->因為變量范圍越小越可控.

------------------LJXPerson.h---------------------
#import <Foundation/Foundation.h>
//
static NSInteger num1 = 99; //定義一個全局靜態變量

@interface LJXPerson : NSObject

/**
 測試方法
 */
- (void)test;
@end

------------------LJXPerson.m---------------------
**LJXPerson.m**
#import "LJXPerson.h"
@implementation LJXPerson

- (void)test{
    num1--;
    NSLog(@"%p   %zd",&num1,num1);
}
@end

------------------main.m-------------------------

 #import <Foundation/Foundation.h>
 #import "LJXPerson.h"
int main(int argc, const char * argv[]) {
    
     //測試全局的靜態變量
    NSLog(@"在LJXPerson中定義的全局靜態變量的地址%p,%zd", &num1,num1);
    num1=777777;
    NSLog(@"在LJXPerson中定義的全局靜態變量的地址%p,%zd", &num1,num1);
   
    LJXPerson *xinge=[LJXPerson new];
    [xinge test];
    
    LJXPerson *xiaoming=[LJXPerson new];
    [xiaoming test];
    
    NSLog(@"在LJXPerson中定義的全局靜態變量的地址%p,%zd", &num1,num1);
    return 0;
}

在LJXPerson中定義的全局靜態變量的地址0x100001190,99
在LJXPerson中定義的全局靜態變量的地址0x100001190,777777
0x100001198 98
0x100001198 97
在LJXPerson中定義的全局靜態變量的地址0x100001190,777777

通過:上面的輸出結果截圖也對剛才上面的闡述得到了驗證,以下代碼第6,7,8,13,14行是調用的外部的,即修改的是地址0x100001190對應的變量的值,只有在對象調用方法時是調用的內部的靜態變量.

    //測試全局的靜態變量
6.   NSLog(@"在LJXPerson中定義的全局靜態變量的地址%p,%zd", &num1,num1);
7.   num1=777777;
8.   NSLog(@"在LJXPerson中定義的全局靜態變量的地址%p,%zd", &num1,num1);
   
9.    LJXPerson *xinge=[LJXPerson new];
10.   [xinge test];
    
11.   LJXPerson *xiaoming=[LJXPerson new];
12.   [xiaoming test];

13.   NSLog(@"在LJXPerson中定義的全局靜態變量的地址%p,%zd", &num1,num1);
14.   return 0;
}

main函數中:注釋掉下面的代碼

//    NSLog(@"在LJXPerson中定義的全局靜態變量的地址%p,%zd", &num1,num1);
//    num1=777777;


在LJXPerson中定義的全局靜態變量的地址0x100001190,99
0x100001198 98
0x100001198 97
在LJXPerson中定義的全局靜態變量的地址0x100001190,99

3.5 靜態變量的正確用法

  1. 先定義局部靜態變量
  2. static 關鍵字定義的變量在程序執行中 只會被執行一次
    • 在 BSS 段為變量分配空間
    • 並且設置初始值,如果沒有指定初始值,會使用 0 作為初始值

即: static 關鍵字的作用

  1. 在 BSS 段為 靜態變量 分配空間
  2. 為 靜態變量 設置初始值,如果沒有指定初始值,會使用 0 來作為初始值
  3. static 關鍵字定義靜態變量的代碼,只會被執行一次

------------------聲明---------------------
#import <Foundation/Foundation.h>
@interface LJXPerson : NSObject
/**
 測試方法
 */
- (void)test;
@end
-------------------實現--------------------
#import "LJXPerson.h"
@implementation LJXPerson
- (void)test{
    static NSInteger num1 = 99;  //定義局部靜態變量
    num1--;
    NSLog(@"%p   %zd",&num1,num1);
}
@end
-------------------主程序--------------------
#import <Foundation/Foundation.h>
#import "LJXPerson.h"
int main(int argc, const char * argv[]) {
    
    LJXPerson *xinge=[LJXPerson new];
    [xinge test];
    
    LJXPerson *xiaoming=[LJXPerson new];
    [xiaoming test];

    return 0;
}

2030-03-31 15:12:48.504 demo[5399:535229] 0x100001170 98
2030-03-31 15:12:48.505 demo[5399:535229] 0x100001170 97
Program ended with exit code: 0

3. 如果當前類文件中,有 多個方法 使用到該靜態變量,再將該靜態變量修改成全局的

------------------聲明---------------------
#import <Foundation/Foundation.h>
@interface LJXPerson : NSObject
/**
 測試方法
 */
- (void)test;
- (void)demo;
@end
-------------------實現--------------------
#import "LJXPerson.h"
//當前類文件中,有 `多個方法` 使用到該靜態變量,放到全局中
static NSInteger num1 = 99;

@implementation LJXPerson
- (void)test{
    num1--;
    NSLog(@"%p   %zd",&num1,num1);
}
- (void)demo{
    num1++;
    NSLog(@"%p   %zd",&num1,num1);
}
@end
-------------------主程序--------------------
#import <Foundation/Foundation.h>
#import "LJXPerson.h"
int main(int argc, const char * argv[]) {
    
    LJXPerson *xinge=[LJXPerson new];
    [xinge test];
    [xinge demo];
   
    LJXPerson *xiaoming=[LJXPerson new];
    [xiaoming test];
    [xiaoming demo];
    return 0;
}

0x1000011b0 98
0x1000011b0 99
0x1000011b0 98
0x1000011b0 99

3.6 常量

作用:定義一個固定不變的值,全局統一使用,eg:公司網址,電話等

  1. const 關鍵字保證其后修飾的常量的值不允許被修改
    常量的工作原理:
    在 程序被加載到內存時,就會為常量分配空間並且設置初始值
    在 數據段 為常量分配空間
    如果沒有指定初始值,會使用 0 作為初始值

  2. 不能把 常量 定義在頭文件中
    (跟全局變量不能定義在頭文件中一樣,會導致重復定義)

  3. 應該在 .m 中定義常量
    比如我們在LJXPerson.m中定義了一個常量,const NSInteger cNumber =100;這時,這個常量只能在LJXPerson.m中使用,怎么才能也能在main.m中使用呢,
    那就需要下面介紹的第4個知識點了.
    在LJXPerson.h頭文件中做聲明.externconst NSInteger cNumber;
    特別注意,不能再給設置初始值了,它已經在其他文件中(eg:在LJXPerson.m中設置值為100了),我們要清楚extern的作用,表示該常量的數值,是在其他文件中設置的,外部可以直接使用此常量)
    總之:

    eg:在.m中: const NSInteger cNumber =100;
    eg:在.h中: extern const NSInteger cNumber;
  4. 在 .h 中使用 extern 關鍵字聲明該 常量 在其他文件設置值

extern的作用:  extern關鍵字,表示該常量的數值,是在其他文件中設置的,
外部可以直接使用此常量.

注意:在一個項目中,常量不能重名,因此在定義常量時,應該盡量長,有前綴,以保證不會出現重名的情況


本篇主要學習目標回顧:


內存五大區域

程序要執行,首先需要被加載到內存

1.1 記憶內存五大區域的名稱

能夠說出內存五大區域的名稱
棧區
堆區
BSS段(靜態區)
數據段(常量區)
代碼段

1.2 記憶棧區/堆區的職責及特點

能夠說出棧區職責(存儲的內容)

  • 局部變量
  • 方法實參

能夠說出棧區的特點
512K
連續
從大到小
速度快
系統管理
能夠說出調用方法時棧區的工作原理
開啟棧幀
保存實參
保存局部變量
方法完成后彈棧,銷毀棧幀,釋放空間
能夠說出堆區的職責(存儲的內容)

  • OC 使用 new 方法創建的對象 由於 ARC 管理機制,OC 程序員通常不需要考慮對象的釋放
  • C 語言使用 malloc 函數分配的空間,需要使用 free 函數釋放

能夠說出堆區的特點
所有程序共享
存儲大數據
程序員管理
不連續
速度沒有棧區快

1.3 記憶全局變量/靜態變量/常量保存的內存區域

開發要讓 變化控制在有限的范圍 內

能夠說出教科書中 全局變量 和 靜態變量 的存儲區域

  • 有初始值 的 全局變量 和 靜態變量 保存在 數據段(常量區)
  • 沒有初始值 的 全局變量 和 靜態變量 保存在 BSS 段(靜態區) 當給 全局變量 或 靜態變量 設置初始值后,會被移動到 數據段(常量區)

能夠說出 Xcode 8 中 全局變量 和 靜態變量 的存儲區域

  • 無論是否設置初始值,全局變量 和 靜態變量 都保存在 BSS 段(靜態區) 能夠說出 常量 的存儲區域 常量 存儲在 數據段(常量區) 能夠說出為什么幾乎不使用 全局變量 開發要讓 變化控制在有限的范圍 內 不能把 全局變量 定義在頭文件中,否則會出現重復定義 ## 1.4 記憶靜態變量/常量的用法

能夠說出 static 關鍵字的作用

  1. 在 BSS 段為 靜態變量 分配空間
  2. 為 靜態變量 設置初始值,如果沒有指定初始值,會使用 0 來作為初始值
  3. static 關鍵字定義靜態變量的代碼,只會被執行一次!

能夠說出靜態變量的正確用法
* 如果只有一個方法使用,將 靜態變量 定義在方法內部
* 如果有多個方法使用,將 靜態變量 定義在 .m 中
* 不要把靜態變量定義在頭文件中

能夠說出常量的作用

定義一個固定不變的值,全局統一使用,例如公司的網址/電話等...
在 iOS 開發中,通常僅僅在定義 通知字符串 時才會使用到常量

能夠說出常量的正確用法

在 .m 中定義常量並且設置初始值
const NSInteger cNum = 99;
在 .h 中使用 extern 關鍵字聲明常量在其他位置定義並且已經賦值,外部可以直接使用
extern const NSInteger cNum;
常量名應該盡量的長以避免出現重名

結束語

ok! 以上關於內存五大區域基礎知識對您起到學習作用了嗎?如果有錯誤之處望指正!謝謝!相關學習共同進步!真心希望其中某個知識點能幫到您!








以上內容目錄結構 (點擊可調轉)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM