2010-12-04 32 views
4

我一直在尋找常量,並且我不明白他們有什麼不同,除非他們不能以編程方式更改。常數的解釋

extern NSString * const MyConstant; 

這條線究竟是什麼意思extern,準確地什麼的const是什麼意思?

回答

19

有人問你兩個問題:一個關於常量,一個關於extern。這兩者不一定相關。

首先,const:沒有太多的常量比,正如你所說的,它們不能以編程方式改變。取決於你如何聲明它們,不同的事物可以是不變的。例如,在你的例子中:

NSString * const MyConstant = @"foo"; 

你已經聲明瞭一個常量指針,指向一個非常量的NSString對象; const關鍵字位於星號的右側,因此它指向指針。因此,這樣的:

MyConstant = @"bar"; 

將導致編譯錯誤,因爲它試圖重新分配MyConstant指向一個不同的NSString。

如果const關鍵字位於星號的左側,它將引用指針引用的對象(在本例中爲底層NSString結構體)。這可能不是你最想要的目的C.時間請注意,相對於類型標識符const關鍵詞的位置並不重要,所以這樣的:

const NSString *MyConstant = @"foo"; 

這:

NSString const *MyConstant = @"foo"; 

表示同樣的事情。您也可以合法地申報指針和參考價值常量兩者最大常量性:

const NSString * const MyConstant = @"foo"; 

其次,EXTERNextern只是允許您在一個編譯單元聲明一個變量,並讓編譯器知道您已經在單獨的編譯單元中定義了該變量。你通常只用於全局值和常量。

您可以將編譯單元視爲單個.m文件,以及它包含的所有.h文件。在編譯時,編譯器會將每個.m文件編譯爲一個單獨的.o文件,然後鏈接器將它們全部掛接到一個二進制文件中。通常,一個編譯單元知道另一個編譯單元中聲明的標識符(例如類名)的方式是導入一個頭文件。但是,對於全局變量,它們通常不是類的公共接口的一部分,所以它們經常在.m文件中聲明和定義。

如果編譯單元中聲明瞭一個全球性的.m文件:

#import "A.h" 

NSString *someGlobalValue; 

和編譯單元B想要使用全球:

#import "B.h" 
extern NSString *someGlobalValue; 

@implementation B 

- (void)someFunc { 
    NSString *localValue = [self getSomeValue]; 
    if (localValue isEqualToString:someGlobalValue]) { 
     ... 
    } 
} 

單元B以某種方式告訴編譯器使用由單元A聲明的變量。它不能導入發生聲明的.m文件,所以它使用extern告訴編譯器該變量存在於其他地方。

注意,如果單元A和單元B 有這條線在文件的頂層:

NSString *someGlobalValue; 

那麼你有兩個編譯單元聲明相同的全局變量,鏈接器將失敗有重複的符號錯誤。如果你想有一個像這樣只存在編譯單元裏面,是看不到任何其他的編譯單元(即使他們使用extern)一個變量,你可以使用static關鍵字:

static NSString * const someFileLevelConstant = @"wibble"; 

這可以用於您想在單個實現文件中使用的常量,但不需要其他位置。

+0

給那些打破它的人歡呼。分解它。 – 2012-09-30 19:47:00

-1

Extern表示該變量設置在聲明的源文件之外。建議使用OBJC_EXPORT標誌而不是extern。

const表示變量設置後無法更改。但是,你可以使用一些指針誤導,如下圖所示:

NSString **var = (NSString **)&MyConstant; 
*var = @"I changed it!"; 

這實際上將讓你改變它,如果你需要(例如,在你的類+initialize法)。

+0

第一段有意義。其餘與這個問題無關(並且沒有意義)。 – bbum 2010-12-04 17:16:12

2
extern NSString * const MyConstant; 

你會在頭文件中看到這個。它告訴編譯器,變量MyConstant存在並且可以在你的實現文件中使用。

多不容易,該變量設置是這樣的:

NSString * const MyConstant = @"foo"; 

值不能被改變。如果您想要一個可以更改的全局,則從聲明中刪除const

+0

你應該很少看到頭文件中的`extern`。存在`extern`關鍵字以允許鏈接程序解析跨翻譯單元使用的符號。如果符號在頭文件中聲明,則不需要使用`extern`;只需導入頭文件。而且,由於全局變量不是類的接口的一部分,因此不需要使用`extern`將一個符號導入到頭文件中。 – 2010-12-04 19:55:55