淺談C語言弱定義機制
前言:前面的文章中,我們詳細介紹了C++中的純虛函數(shù),作者聯(lián)想到C語言中的一個思想與C++的純虛函數(shù)有異曲同工之妙,那就是弱定義。弱定義這個概念,可能做嵌入式開發(fā)的童鞋接觸的會比較多,本文跟大家一起來學習一下。
一、弱定義的概念
C語言弱定義是通過特定修飾符聲明函數(shù)或變量的技術,本質是上是一套鏈接期的符號決議規(guī)則:同一個全局符號(函數(shù)或變量)允許出現(xiàn)多份定義,其中最多只有一份“強定義”,其余都是“弱定義”。在鏈接過程中優(yōu)先選擇強定義的符號,而弱定義僅在沒有強定義時被使用。
弱定義特點:
- 允許符號在鏈接時被覆蓋
- 提供默認實現(xiàn),可被強定義替換
- 常用于庫函數(shù)的可覆蓋實現(xiàn)
- 在gcc中通過 __attribute__((weak)) 聲明
__attribute__((weak))
二、弱定義與強定義區(qū)別
特性 | 強定義 | 弱定義 |
符號類型 | T (Text), D (Data) | W (Weak) |
可覆蓋性 | 不可被覆蓋 | 可被強定義覆蓋 |
多重定義 | 導致鏈接錯誤 | 允許存在多個定義 |
內存占用 | 一定會被編譯進最終二進制文件(.elf/.hex) | 不一定。若有強定義覆蓋,則不會被編譯進去 |
使用場景 | 普通函數(shù)/變量 | 默認實現(xiàn)、鉤子函數(shù)等 |
| 優(yōu)先級 | 最高 | 最低 |
| 形象比喻 | 正式工 | 臨時工/備胎 |
三、弱定義語法
3.1 使用__attribute__((weak))
// 弱定義一個函數(shù)
__attribute__((weak)) void weak_function(void) {
printf("這是弱定義函數(shù)\n");
}
// 弱定義一個變量
__attribute__((weak)) int weak_var = 10;
3.2 使用#pragma weak
#pragma weak funcA
void funcA() {
// ... 默認行為
}一般普遍使用的是第一種格式。
四、鏈接過程
鏈接器在解析符號時遵循以下規(guī)則:
- 如果只有一個強定義,選擇該定義
- 如果有多個強定義,報告多重定義錯誤
- 如果有一個弱定義和一個強定義,選擇強定義
- 如果有多個弱定義,任選一個(通常是第一個遇到的)

看到這里,大家有沒有覺得弱定義的這種機制,是不是有點像C++中的虛函數(shù)/純虛函數(shù):基類提供“默認實現(xiàn)”的虛函數(shù)/純虛函數(shù),派生類重寫來“覆蓋”基類的默認行為。(兩者的相似性,童鞋們可以細細品味)
五、代碼示例 — 弱函數(shù)的定于與覆蓋
1)定義并使用弱函數(shù):
// weak_example.c
#include <stdio.h>
// 弱定義函數(shù)
__attribute__((weak)) void my_function(void) {
printf("默認的弱定義函數(shù)被調用\n");
}
int main(void) {
my_function(); // 調用函數(shù)
return 0;
}
2)編譯運行:
$ gcc weak_example.c -o weak_example $ ./weak_example 默認的弱定義函數(shù)被調用
3)強定義覆蓋:
// strong_override.c
#include <stdio.h>
// 普通的強定義函數(shù)
void my_function(void) {
printf("強定義函數(shù)覆蓋\n");
}
4)編譯運行weak_example.c與strong_overrid.c文件:
$ gcc weak_example.c strong_override.c -o override_example $ ./override_example 強定義函數(shù)覆蓋
六、典型使用場景
6.1 庫的默認實現(xiàn)
在開發(fā)庫時,可以使用弱定義提供函數(shù)的默認實現(xiàn),允許用戶通過提供強定義來覆蓋默認行為。好處:庫保持默認行為,用戶無需修改庫源碼即可定制功能。
6.2 中斷處理函數(shù)
在嵌入式系統(tǒng)中,默認中斷處理函數(shù)通常定義為弱定義,允許應用程序根據(jù)需要提供特定的中斷處理實現(xiàn)。好處:避免未定義中斷導致崩潰,且支持用戶靈活定制中斷處理邏輯。
到此這篇關于淺談C語言弱定義機制的文章就介紹到這了,更多相關C語言弱定義內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
深入理解:Java是類型安全的語言,而C++是非類型安全的語言
本篇文章是對Java是類型安全的語言,而C++是非類型安全的語言進行了詳細的分析介紹,需要的朋友參考下2013-06-06
C++實現(xiàn)LeetCode(179.最大組合數(shù))
這篇文章主要介紹了C++實現(xiàn)LeetCode(179.最大組合數(shù)),本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下2021-08-08
c++ dynamic_cast與static_cast使用方法示例
本文用示例講解了dynamic_cast、static_cast子類與基類之間轉換功能的使用方法2013-11-11
ubuntu系統(tǒng)vscodeC++編譯環(huán)境配置與使用方式
這篇文章主要介紹了ubuntu系統(tǒng)vscodeC++編譯環(huán)境配置與使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12
C++實現(xiàn)LeetCode(143.鏈表重排序)
這篇文章主要介紹了C++實現(xiàn)LeetCode(143.鏈表重排序),本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下2021-07-07
詳解C++編程中的靜態(tài)成員與可變數(shù)據(jù)成員
這篇文章主要介紹了詳解C++編程中的靜態(tài)成員與可變數(shù)據(jù)成員,是C++入門學習中的基礎知識,需要的朋友可以參考下2016-01-01

