extern
下面的代碼聲明了一個全局變量,它用于告訴編譯器:“你現在編譯的文件中,有一個標識符雖然沒有在本文件中定義,但是它是在別的文件中定義的全局變量,你要在其它文件內查找!”
extern int a;//聲明一個全局變量a
請確保該變量已經在其它文件內定義!
如果該變量沒有在其他文件中定義,編譯器會報錯。
比如,在某版本的 Xcode 下,會有如下報錯:
Undefined symbols for architecture arm64:
"_b", referenced from:
-[AppDelegate application:didFinishLaunchingWithOptions:] in AppDelegate.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code (use -v to see invocation)
const
const 關鍵字指定變量的值是常量,并通知編譯器防止程序員修改它。
當我們嘗試直接修改時,編譯器會報錯??。比如下面的代碼在Xcode 8 中,會提示Cannot assign to variable 'const_i' with const-qualified type 'const int'
。
const int const_i = 10;
const_i = 20;
程序運行時,對 const
關鍵字指定的變量?進行修改的行為是未定義(undefined)的,它主要由編譯器所決定。
static
在全局變量前,加上關鍵字static,該變量就被定義成為一個靜態全局變量。
靜態全局變量在聲明它的整個文件都是可見的,而在文件之外是不可見的。
靜態變量都在全局數據區分配內存。
static NSString *name;
name = @"酷酷的哀殿";
NSLog(@"%p", name);
NSString *nameba = @"酷酷的哀殿";
NSLog(@"%p", &nameba);
NSString *nameb = @"酷酷的哀殿";
NSLog(@"%p", &nameb);
靜態變量和局部變量的地址并不在同一個區域
0x1000ec070
0x16fd1a1f8
0x16fd1a1f0
下面兩種全局變量聲明的區別是,如果多個文件內存在同名變量,int a
會導致duplicate symbol _a
static int a;
int a;
其它用法
定義外部使用的常量。
為了方便讓外部使用變量,推薦使用以下方法
//在.h文件內進行如下聲明
FOUNDATION_EXTERN NSString *const kSUNName;
//或
UIKIT_EXTERN NSString *const kSUNName;
并在.m文件內定義
NSString *const kSUNName = @"酷酷的哀殿";
請注意,這里不能添加static
修飾符。用static
修飾后,將不能提供外界訪問。比如下面的寫法:
static const NSString *SUNName = @"酷酷的哀殿";
在其他地方使用會報錯
Undefined symbols for architecture arm64:
"_SUNName", referenced from:
-[AppDelegate application:didFinishLaunchingWithOptions:] in AppDelegate.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
擴展知識
但是,當我們通過 extern
關鍵字重新聲明其它文件內的變量時,編譯器會忽略原先的關鍵字。所以,我們可以通過下面的方法修改可以取消報錯??。
//A文件
const int sun_i = 10;
const int * const sun_j = &sun_i;
//B文件
extern int sun_i;
extern int *sun_j;
*sun_j = 100;
printf("%d",sun_i);