C 鏈接屬性淺析

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將導致未定義行爲。

因此應避免這類情況的發生。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章