利用匯編理解iOS中的static const extern關鍵字

在iOS開發中會經常使用到static const extern3個關鍵字, 一直對這3個關鍵字很模糊, 這里總結一下, 做一個筆記.

一.const關鍵字

const通常被用來修飾字符串常量, 其作用和宏類似.

宏定義是預編譯指令, 在編譯之前處理, 宏不做檢查不會報編譯錯誤, 只是簡單的替換. const會編譯階段, 會做編譯檢查報編譯錯誤.

宏可以用來定義一些函數和方法, 而const只能用來定義變量常量.
在項目中大量使用宏定義, 會使項目的編譯時長大大增加.

NSString * const a = @"123";

a的值是無法修改的.

const其實是編譯器特性, 那么我們如何去理解const呢?

int a = 10;
int b = 20;

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int c = a;
        c = b;
    }
    return 0;
}

通過對上訴代碼反匯編如下:

image

將變量b修改為const修飾, 代碼如下

int a = 10;
int const b = 20;

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int c = a;
        c = b;
    }
    return 0;
}

對上訴代碼進行反匯編, 如下:

image

對比兩次反匯編的代碼, 變量a存儲在數據段全局區, 而對變量b進行const修飾以后, 變量b直接被替換為立即數$0x14(也就是十進制的20), 所以被const修飾以后, 變量b的值就不能修改了.

二.static關鍵字

static關鍵字用來修飾變量的作用域. static修飾的變量只會分配一份內存.

static修飾局部變量, 在上一次修改的基礎上進行修改

-(void)staticDemo1
{
    int a2 = 0
    static int a1 = 0;
    a1++;
    NSLog(@"%zd", a1);
}

局部變量a2的內存分布在棧上, 而靜態變量a1的內存是分布在數據段的全局區, 沒執行一次staticDemo1方法變量a2的值都被重新賦值為0, 而a1在常量區, 內存地址不會發生變化, 還是取的之前賦的值

無論調用幾次方法, a1的內存只有一份, 多次被調用時a1是在原來的基礎上修改的. 輸出結果為 1 2 3

static修飾全局變量, 在當前文件中可用, 在不同函數中調用修改, 會在上一個函數的基礎上修改

static int a2 = 3;

- (void)viewDidLoad {
    [super viewDidLoad];
    [self staticDemo2];
    [self staticDemo3];
    [self staticDemo2];
    [self staticDemo3];
}

-(void)staticDemo2
{
    a2++;
    NSLog(@"%zd", a2);
}

-(void)staticDemo3
{
    a2++;
    NSLog(@"%zd", a2);
}

結果: 4 5 6 7

靜態全局變量和非靜態全局變量的區別:
static限制了變量的作用域為當前文件, 其他文件可以定義一個相同的static變量, 如果沒有static修飾, 在其他文件中定義了相同名稱的全局變量, 會報錯.

思考: 為什么在不同的文件中用static定義相同名稱的變量, 不會報重復定義的錯誤呢?

猜想: 用static定義相同名稱的變量, 被分布到數據段全局區不同內存地址上.

在main函數中執行下列函數, 為了獲取static int a變量的地址, 在函數中將的值賦值給一個局部變量.

#include "StaticTest.h"

static int a = 10;

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int c = a;
        staticTest();
    }
    return 0;
}

StaticTest.c中定義如下函數

static int a = 20;

void staticTest() {
    int b = a;
}

分別在int c = aint b = a處打斷點, 查看匯編代碼如下:

image
image

通過查看匯編, 計算出a變量的地址分別為0x1000010280x10000102C, 查看這兩個地址存放的數據.

image
image

兩個地址分別存儲10和20.

三.extern關鍵字

只能用來獲取全局變量的值, 不能用于定義變量

四.混搭使用

static和const

static NSString * const name = @"OneAlon";

extern和const, 在多個文件中經常使用的字符串常量, 通常創建一個GlobeConst文件用于管理全局變量, 統一管理.

@interface GlobeConst : NSObject

extern NSString * const nameKey;

@end

------------------------------------------

@implementation GlobeConst

NSString * const nameKey = @"OneAlon";

@end
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容