C语言 弱定义机制 解读
前言前面的文章中我们详细介绍了C中的纯虚函数作者联想到C语言中的一个思想与C的纯虚函数有异曲同工之妙那就是弱定义。弱定义这个概念可能做嵌入式开发的童鞋接触的会比较多本文跟大家一起来学习一下。目录一、弱定义的概念二、弱定义与强定义区别三、弱定义语法3.1 使用__attribute__((weak))3.2 使用#pragma weak四、链接过程五、代码示例 — 弱函数的定于与覆盖六、典型使用场景6.1 库的默认实现6.2 中断处理函数一、弱定义的概念C语言弱定义是通过特定修饰符声明函数或变量的技术本质是上是一套链接期的符号决议规则同一个全局符号函数或变量允许出现多份定义其中最多只有一份“强定义”其余都是“弱定义”。在链接过程中优先选择强定义的符号而弱定义仅在没有强定义时被使用。弱定义特点允许符号在链接时被覆盖提供默认实现可被强定义替换常用于库函数的可覆盖实现在gcc中通过__attribute__((weak))声明__attribute__((weak))二、弱定义与强定义区别特性强定义弱定义符号类型T (Text), D (Data)W (Weak)可覆盖性不可被覆盖可被强定义覆盖多重定义导致链接错误允许存在多个定义内存占用一定会被编译进最终二进制文件(.elf/.hex不一定。若有强定义覆盖则不会被编译进去使用场景普通函数/变量默认实现、钩子函数等优先级最高最低形象比喻正式工临时工/备胎三、弱定义语法3.1 使用__attribute__((weak))// 弱定义一个函数 __attribute__((weak)) void weak_function(void) { printf(这是弱定义函数\n); } // 弱定义一个变量 __attribute__((weak)) int weak_var 10;3.2 使用#pragma weak#pragma weak funcA void funcA() { // ... 默认行为 }一般普遍使用的是第一种格式。四、链接过程链接器在解析符号时遵循以下规则如果只有一个强定义选择该定义如果有多个强定义报告多重定义错误如果有一个弱定义和一个强定义选择强定义如果有多个弱定义任选一个通常是第一个遇到的看到这里大家有没有觉得弱定义的这种机制是不是有点像C中的虚函数/纯虚函数基类提供“默认实现”的虚函数/纯虚函数派生类重写来“覆盖”基类的默认行为。两者的相似性童鞋们可以细细品味五、代码示例 — 弱函数的定义与覆盖1定义并使用弱函数// weak_example.c #include stdio.h // 弱定义函数 __attribute__((weak)) void my_function(void) { printf(默认的弱定义函数被调用\n); } int main(void) { my_function(); // 调用函数 return 0; }2编译运行$ gcc weak_example.c -o weak_example $ ./weak_example 默认的弱定义函数被调用3强定义覆盖// strong_override.c #include stdio.h // 普通的强定义函数 void my_function(void) { printf(强定义函数覆盖\n); }4编译运行weak_example.c与strong_overrid.c文件$ gcc weak_example.c strong_override.c -o override_example $ ./override_example 强定义函数覆盖六、典型应用场景6.1 库的默认实现在开发库时可以使用弱定义提供函数的默认实现允许用户通过提供强定义来覆盖默认行为。好处库保持默认行为用户无需修改库源码即可定制功能。6.2 中断处理函数在嵌入式系统中默认中断处理函数通常定义为弱定义允许应用程序根据需要提供特定的中断处理实现。好处避免未定义中断导致崩溃且支持用户灵活定制中断处理逻辑。