C語言鏈接屬性的實(shí)踐應(yīng)用
什么是鏈接屬性
鏈接屬性與C語言中各個目標(biāo)文件及函數(shù)的鏈接過程有關(guān),用于認(rèn)定不同文件的標(biāo)識符(即程序中定義的各種名稱,包括變量名、函數(shù)名)是否是同一個實(shí)體。更通俗地說,就是在兩個不同文件中的變量、函數(shù)聲明是否指向同一個實(shí)體。比如:a、b文件同時聲明了變量c,鏈接屬性就指定了這兩處變量c是否是同一個c。
簡單來說,鏈接屬性的作用就是讓你能在a文件中決定要不要訪問b文件中的變量、函數(shù)。
鏈接屬性的分類
鏈接屬性有三種:
- external - 外部鏈接
- internal - 內(nèi)部鏈接
- none - 無鏈接
對于external屬性的標(biāo)識符,不同文件中出現(xiàn)的多個同名稱標(biāo)識符指向同一個實(shí)體。在C語言中,用extern關(guān)鍵字在聲明中指定以引用其他文件中定義的相同標(biāo)識符。
對于internal屬性的標(biāo)識符,僅在當(dāng)前文件內(nèi)該標(biāo)識符指向同一個實(shí)體。在C語言中,用static關(guān)鍵字在聲明中指定讓標(biāo)識符變?yōu)樵撐募接?/strong>(只有對原本缺省的鏈接屬性為external的標(biāo)識符,才能用static關(guān)鍵字改變其鏈接屬性為internal)。
對于none屬性的標(biāo)識符,在每個聲明位置都是一個新的實(shí)體。C語言中,沒有對應(yīng)的關(guān)鍵字。
默認(rèn)的鏈接屬性
標(biāo)識符的默認(rèn)的鏈接屬性與其出現(xiàn)的位置有關(guān)。
程序的全局變量、所有函數(shù)默認(rèn)的鏈接屬性為external。
其余標(biāo)識符的默認(rèn)鏈接屬性為none。
在以下例子中,b、c、f的鏈接屬性就是external:
typedef char *a;
int b;
int c(int d)
{
int e;
int f(int g);
}
實(shí)踐應(yīng)用
extern
在a文件中想要使用b文件中定義的external屬性標(biāo)識符,可使用extern關(guān)鍵字在a文件中聲明。
即使該標(biāo)識符所在位置默認(rèn)鏈接屬性為external,也建議使用extern關(guān)鍵字顯式說明,有利于增加程序可讀性。
static
在a文件定義了一個全局標(biāo)識符,但不想被其他文件訪問,可以對該標(biāo)識符加上static關(guān)鍵字。
在a、b文件中定義了同樣的標(biāo)識符,通過static關(guān)鍵字可以避免多重定義問題。
再次提醒:只有對原本缺省的鏈接屬性為external的標(biāo)識符,才能用static關(guān)鍵字改變其鏈接屬性為internal
一些細(xì)節(jié)
- 對于external屬性的標(biāo)識符,你可以在多個不同源文件中聲明,但是你只能在一處初始化。否則就會出現(xiàn)重復(fù)定義的問題:
multiple definition of 'a';。 - extern關(guān)鍵字聲明的標(biāo)識符用于訪問其他文件中定義的同名的標(biāo)識符,因此無法進(jìn)行初始化。如果你對extern聲明的變量進(jìn)行初始化就會生成警告:
warning: ‘a’ initialized and declared ‘extern’。 - 如果在其他文件中不存在相應(yīng)的標(biāo)識符定義,卻在當(dāng)前文件中使用了extern聲明,會報錯:
undefined reference to 'a',原理同2。 - external屬性的標(biāo)識符總是靜態(tài)存儲類型。
- static關(guān)鍵字還有改變存儲類型的作用,因此,其作用與上下文環(huán)境有關(guān),只有對于默認(rèn)鏈接屬性為external的標(biāo)識符,才有改變鏈接屬性的作用。
- C++中,const變量隱含的具有internal屬性,C中并不具有這一性質(zhì)。
思考題
internal和none屬性除了作用域不同還有什么區(qū)別?
以下代碼一定程度上闡釋了部分區(qū)別:
static int i; // definition
// static storage
// internal linkage
void f(void)
{
extern int i; // declaration
// refers to the static i at file scope
// note that even though the specifier is extern
// its linkage is intern (this is legal in both C/C++)
{
int i; // definition
// automatic storage
// no linkage
}
}
實(shí)際上鏈接屬性和作用域是兩個概念。之所以產(chǎn)生以上問題,因?yàn)閕nternal屬性標(biāo)識符出現(xiàn)的位置都是在文件作用域,而none往往在代碼塊作用域。此處想引起讀者對內(nèi)鏈接更深入的思考,見問題2。
文件作用域已經(jīng)能讓程序訪問同一文件變量,那么再進(jìn)行內(nèi)部鏈接的意義在哪?
同一個標(biāo)識符在鏈接中只能存在一個,那么通過內(nèi)部鏈接的方式可以隔絕同名外部鏈接,且限定了外部編譯單元不能訪問該文件全局標(biāo)識符。
a.c:
#include <stdio.h>
static int a=3;
int main(void)
{
extern int a;
printf("a=%d\n", a);
return 0;
}
b.c:
int a=1;
編譯后結(jié)果為:
a=3
以上僅為不完善的個人猜想,拋開隔絕外部鏈接這一點(diǎn)不談,就內(nèi)部鏈接這一名稱而言,筆者對為什么要在同一個文件內(nèi)部使用鏈接的設(shè)計仍然存疑,但目前該話題的答案超出了筆者的理解,因此更深入的討論暫時留白。
拓展:感興趣的同學(xué)可以嘗試學(xué)習(xí)鏈接相關(guān)知識,或許會找到更確定的答案。
參考
《Pointers On C》
總結(jié)
到此這篇關(guān)于C語言鏈接屬性的文章就介紹到這了,更多相關(guān)C語言鏈接屬性內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++ vector容器 find erase的使用操作:查找并刪除指定元素
這篇文章主要介紹了C++ vector容器 find erase的使用操作:查找并刪除指定元素,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-05-05
C++下如何將TensorFlow模型封裝成DLL供C#調(diào)用
這篇文章主要介紹了C++下如何將TensorFlow模型封裝成DLL供C#調(diào)用問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-11-11
C語言實(shí)現(xiàn)動態(tài)擴(kuò)容的string
最近工作中使用C語言,但又苦于沒有高效的字符串實(shí)現(xiàn),字符串的拼接和裁剪都很麻煩,而且每個字符串都需要申請內(nèi)存,內(nèi)存的申請和釋放也很容易出bug,怎么高效的實(shí)現(xiàn)一個不需要處理內(nèi)存問題并且可以動態(tài)擴(kuò)容進(jìn)行拼接和裁剪的string呢?本文就來詳細(xì)講講2023-04-04
C語言程序設(shè)計第五版譚浩強(qiáng)課后答案(第二章答案)
這篇文章主要介紹了C語言程序設(shè)計第五版譚浩強(qiáng)課后答案(第二章答案),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2021-04-04

