C 鏈接屬性淺析
鏈接屬性用於處理多個文件中同名標識符是否指向同一實體的問題。C 中有三種鏈接屬性——None,Internal和External。讓我們分別看看這三種類型。
- None:表示該標識符沒有其他鏈接,總是獨立的。也就是說這些標識符都會指向獨立的、不同的實體
- Internal:表示在同一文件中聲明的標識符都會指向同一實體,而不同文件中聲明的同名標識符則會指向其他實體
- 換言之,它修飾的變量僅能在本文件使用,其他文件無法訪問
- External:表示無論在哪聲明該標識符,也無論聲明多少次,它們都會指向同一實體
- 換言之,它修飾的變量可以引用其他文件中定義的變量
代碼分析
看下代碼就明白三者的不同了:
None
//FileOne.c
void foo()
{
int var;
}
//FileTwo.c
void func()
{
int var;
}
局部變量就是一個很好的例子。這兩個變量雖然同名,但會被獨立的處理開來,它們指向的是不同的實體。
Internal
該類型的鏈接需要static關鍵字修飾。
//FileOne.c
static int var = 0x7f;
var只能在FileOne中被使用,其他文件無法訪問此變量。也就是說,FileOne中聲明的所有var都將指向同一個實體,而其他文件中聲明的var將指向不同實體。
External
該類型需要使用extern關鍵字修飾
//FileOne.c
int var = 123;
//FileTwo.c
extern int var; //TIP : 這是聲明語句,而非定義語句。聲明語句不會申請新空間,而定義會
printf("%d",var); //123
可見FileTwo文件聲明的同名標識符var也指向了同FileOne一樣的實體。
變量所屬鏈接屬性的判別
這裏有幾個基本的準則:
- 具有代碼塊作用域或函數原型作用域的變量屬於None鏈接屬性
- 如函數中的局部變量
- 全局變量(函數等)默認擁有external鏈接屬性
- 變量一經定義其鏈接鏈接屬性就不能被改變
對於第二點我們舉例說明一下:
//FileOne.c
int a = 123;
//FileTwo.c
#include <stdio.h>
#include <stdlib.h>
/**
* 全局變量默認具有external鏈接屬性,實際上此句話等價於:
* extern int a;
* */
int a;
int main()
{
printf("%d",a);//123;
return EXIT_SUCCESS;
}
此外有個特殊的情況需要注意一下:
int main()
{
extern int b;
int b = 456;
}
對於這種同作用域下對同變量施加不同鏈接屬性的情況,在筆者Mac中的Eclipse下無法通過編譯,提示“ non-extern declaration of ‘b’ follows extern declaration”。即使這兩個語句調換一下也有不可以。筆者後在網上找到了對此情況的說明:
Two declarations of a in the same scope with different linkage give undefined behaviour.
在同作用域中,聲明兩個具有不同鏈接屬性的變量a將導致未定義行爲。
因此應避免這類情況的發生。