網站首頁 編程語言 正文
什么是鏈接屬性
鏈接屬性與C語言中各個目標文件及函數的鏈接過程有關,用于認定不同文件的標識符(即程序中定義的各種名稱,包括變量名、函數名)是否是同一個實體。更通俗地說,就是在兩個不同文件中的變量、函數聲明是否指向同一個實體。比如:a、b文件同時聲明了變量c,鏈接屬性就指定了這兩處變量c是否是同一個c。
簡單來說,鏈接屬性的作用就是讓你能在a文件中決定要不要訪問b文件中的變量、函數。
鏈接屬性的分類
鏈接屬性有三種:
- external - 外部鏈接
- internal - 內部鏈接
- none - 無鏈接
對于external屬性的標識符,不同文件中出現的多個同名稱標識符指向同一個實體。在C語言中,用extern關鍵字在聲明中指定以引用其他文件中定義的相同標識符。
對于internal屬性的標識符,僅在當前文件內該標識符指向同一個實體。在C語言中,用static關鍵字在聲明中指定讓標識符變為該文件私有(只有對原本缺省的鏈接屬性為external的標識符,才能用static關鍵字改變其鏈接屬性為internal)。
對于none屬性的標識符,在每個聲明位置都是一個新的實體。C語言中,沒有對應的關鍵字。
默認的鏈接屬性
標識符的默認的鏈接屬性與其出現的位置有關。
程序的全局變量、所有函數默認的鏈接屬性為external。
其余標識符的默認鏈接屬性為none。
在以下例子中,b、c、f的鏈接屬性就是external:
typedef char *a; int b; int c(int d) { int e; int f(int g); }
實踐應用
extern
在a文件中想要使用b文件中定義的external屬性標識符,可使用extern關鍵字在a文件中聲明。
即使該標識符所在位置默認鏈接屬性為external,也建議使用extern關鍵字顯式說明,有利于增加程序可讀性。
static
在a文件定義了一個全局標識符,但不想被其他文件訪問,可以對該標識符加上static關鍵字。
在a、b文件中定義了同樣的標識符,通過static關鍵字可以避免多重定義問題。
再次提醒:只有對原本缺省的鏈接屬性為external的標識符,才能用static關鍵字改變其鏈接屬性為internal
一些細節
- 對于external屬性的標識符,你可以在多個不同源文件中聲明,但是你只能在一處初始化。否則就會出現重復定義的問題:
multiple definition of 'a';
。 - extern關鍵字聲明的標識符用于訪問其他文件中定義的同名的標識符,因此無法進行初始化。如果你對extern聲明的變量進行初始化就會生成警告:
warning: ‘a’ initialized and declared ‘extern’
。 - 如果在其他文件中不存在相應的標識符定義,卻在當前文件中使用了extern聲明,會報錯:
undefined reference to 'a'
,原理同2。 - external屬性的標識符總是靜態存儲類型。
- static關鍵字還有改變存儲類型的作用,因此,其作用與上下文環境有關,只有對于默認鏈接屬性為external的標識符,才有改變鏈接屬性的作用。
- C++中,const變量隱含的具有internal屬性,C中并不具有這一性質。
思考題
internal和none屬性除了作用域不同還有什么區別?
以下代碼一定程度上闡釋了部分區別:
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 } }
實際上鏈接屬性和作用域是兩個概念。之所以產生以上問題,因為internal屬性標識符出現的位置都是在文件作用域,而none往往在代碼塊作用域。此處想引起讀者對內鏈接更深入的思考,見問題2。
文件作用域已經能讓程序訪問同一文件變量,那么再進行內部鏈接的意義在哪?
同一個標識符在鏈接中只能存在一個,那么通過內部鏈接的方式可以隔絕同名外部鏈接,且限定了外部編譯單元不能訪問該文件全局標識符。
a.c:
#includestatic int a=3; int main(void) { extern int a; printf("a=%d\n", a); return 0; }
b.c:
int a=1;
編譯后結果為:
a=3
以上僅為不完善的個人猜想,拋開隔絕外部鏈接這一點不談,就內部鏈接這一名稱而言,筆者對為什么要在同一個文件內部使用鏈接的設計仍然存疑,但目前該話題的答案超出了筆者的理解,因此更深入的討論暫時留白。
拓展:感興趣的同學可以嘗試學習鏈接相關知識,或許會找到更確定的答案。
參考
《Pointers On C》
Difference between internal and no linkage
總結?
原文鏈接:https://www.cnblogs.com/p0ise/p/c-language-linkage.html
相關推薦
- 2023-01-08 Android?IntentFilter的匹配規則示例詳解_Android
- 2022-09-15 C語言編寫實現學生管理系統_C 語言
- 2022-05-28 C語言實現宿舍管理課程設計_C 語言
- 2024-03-28 mac vscode 命令行啟動命令安裝 別名設置方法
- 2022-12-11 Django?auth?應用模塊詳解_python
- 2022-08-21 Python命令行庫click的具體使用_python
- 2023-03-13 Android?SRT字幕文件基礎操作講解_Android
- 2022-04-01 Kubernetes命令行工具--kubectl管理
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支