<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
引言:最近在看 linux 中一些驅動程式碼。驅動程式碼中為了實現程式的擴充套件性和相容性用了很多 C 語言中的高階特性。本節就來談一談 C 語言中的弱符號和弱參照的用法。
弱符號是指在定義或者宣告一個物件(變數、結構體成員、函數)時,在物件的前面新增 __attribute__((weak))
標誌所得到的物件符號。如下所示函數即為一個弱物件符號 void test_weak_attr(void)
,或者稱該函數是弱函數屬性的、虛擬函式。
__attribute__((weak)) void test_weak_attr(void) // 或者使用如下樣式的定義,兩者等效 void __attribute__((weak)) test_weak_attr(void) { printf("Weak Func!rn"); }
弱符號是相對於強符號而言的,在定義或者宣告變數、函數時,未新增 __attribute__((weak))
標識的就預設為強符號。如下,最普通的函數定義,就是定義了一個強符號 void test_strong_ref(void):
void test_weak_attr(void) { printf("this is a strong funcrn"); }
驅動程式往往需要考慮相容性,因為要兼任很多廠商的不同型號的裝置。若驅動程式中使用強符號定義一些與適配的裝置的特性相關的功能,則下次適配其他裝置時,該強符號函數可能需要被修改,以相容新的裝置。當適配的裝置很多時,頻繁地更改驅動程式碼將破壞驅動的可維護性。
弱符號的出現可以很好地解決該問題。弱符號的物件具有可以被重定義的功能(即可以被過載)。下面通過測試說明弱符號這種可被過載的特性。
在 test_weak_attr.c 程式中定義如下弱函數:
// test_weak_attr.c #include <stdio.h> __attribute__((weak)) void test_weak_attr(void) { printf("this is a weak funcrn"); }
在 main.c 中定義如下程式:
// main.c void test_weak_attr(void) { printf("this is a strong funcrn"); } void app_main(void) { printf("init donern"); test_weak_attr(); }
編譯執行該 main.c 程式,得到的結果是什麼樣子的呢?
this is a strong func
將 main.c 中的 void test_weak_attr(void) 函數註釋掉,再重新編譯執行程式得到的結果是:
this is a weak func
小結:在使用弱符號函數時,我們可以重新定義一個同名的強符號函數來替代它;若沒有重新定義一個強函數來替換它,就使用弱函數的實現。弱函數就好像是一個可以被替換的“預設函數”。
值得一提的是,舊版本的編譯器還可以使用如下方式的定義(僅宣告無效)將一個物件定義為一個弱物件:
__weak void f(void) { //code }
在 linux 的一些程式碼中,__weak
其實就是通過 __attribute__((weak))
的重新命名,兩者等效。
弱參照是在宣告一個物件時,通過__attribute__ ((weakref())
定義一個符號的參照關係。如下所示即定義 test_weakref() 函數弱參照 test_weak_ref() 函數。
static void test_weakref(void) __attribute__ ((weakref("test_weak_ref")));
弱參照是相對於強參照而言的。未通過 __attribute__ ((weakref())
的符號和實現程式碼之間的關係是強參照。如下即為一個強參照函數。它直接給出了 函數 test_strong_ref(void)
的實現。
static void test_strong_ref(void) { printf("this is a strong refrn"); }
在編譯程式的時候,我們可以直接使用 test_strong_ref(void)
而不必擔心編譯不通過。如果,我沒有時間去實現 test_strong_ref(void) ,還想在程式裡先使用該函數那該如何呢?(是的,就是想白嫖,不想實現,還想先在程式裡使用這個函數)。
這個時候弱參照就派上用場了。可以先將該函數定義為弱參照插入到程式碼中,待後期有時間再慢慢優化程式碼實現這個函數完整的功能。下面結合測試進行說明。
static void test_weakref(void) __attribute__ ((weakref("test_weak_ref"))); void app_main(void) { printf("init donern"); if (test_weakref) { test_weakref(); } else { printf("There is no weakrefrn"); } }
測試結果:
There is no weakref
void test_weak_ref(void) { printf("this is a weak refn"); } static void test_weakref(void) __attribute__ ((weakref("test_weak_ref"))); void app_main(void) { printf("init donern"); if (test_weakref) { test_weakref(); } else { printf("There is no weakrefrn"); } }
測試結果:
this is a weak ref
小結: 強參照,在未定義該強參照的實現時,編譯會報錯誤:未定義的參照。弱參照允許定義一個未實現(未範例化)的物件,這在編譯的時候會將該物件處理成 NULL
,編譯器並不會報錯。通過使用弱參照可以實現後期優化程式碼的功能。而避免改動使用該函數的地方。使用弱函數可以實現類似“勾點(hook)"函數的功能。
實際上,包括C、python、go 程式語言在內的很多語言 都有類似用法,本篇文章敘述的方法同樣適用於這些語言的相關開發。
注意:弱參照僅在靜態編譯中有效,動態連結中可能無效。
弱符號、弱參照都是增強程式的可維護性的方法。弱符號通過可以被重定義的特性,實現可以被替換實現。弱參照通過可以暫時使用一個未定義的函數的功能,實現允許後期再實現該函數具體功能,而不必擔心編譯不通過。
本篇文章就到這裡了,希望能夠給你帶來幫助,也希望您能夠多多關注it145.com的更多內容!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45