嵌入式中的强符号和弱符号是什么?

💡 原文中文,约2200字,阅读约需6分钟。
📝

内容提要

GNU C编译器指令__attribute__用于提供变量、函数等的属性,优化代码并提供注解。强符号和弱符号可共存,编译器根据规则选择符号。强引用和弱引用用于链接操作,弱引用可使用其他模块中定义的实体。弱符号和弱引用在库的实现中有用。

🔎

延伸解读

强弱符号的取舍规则与风险

文章指出,GCC对强弱符号的取舍有明确规则:两个强符号冲突会报错;强弱共存时选强符号;两个弱符号则选占用空间较大的。这种规则虽能避免溢出等问题,但也意味着开发者需留意符号的默认类型,否则可能因未初始化变量被当作弱符号而引发意外覆盖。

弱引用在现代编译器中的使用限制

文章提到,用__attribute__((weakref))声明弱引用时,现代编译器会警告需要配合alias属性才能正常使用。示例中直接声明弱引用函数并判断是否为空的做法虽能编译,但行为不正确。这提醒读者,弱引用并非简单声明即可,需遵循编译器的具体约束。

强弱机制在库设计中的实用价值

弱符号和弱引用常用于库的实现:库可将扩展函数定义为弱符号,允许用户自定义同名函数覆盖;也可将扩展功能定义为弱引用,用户不定义时链接不报错。这使得库的功能可以灵活裁剪和组合,但需注意这是GCC特有特性,MS C编译器不支持。

❓

Q&A

GCC中强符号和弱符号是怎么定义的?默认情况下哪些是强符号哪些是弱符号?

在GCC中,函数和已初始化的全局变量默认被视为强符号,而未初始化的全局变量被视为弱符号。开发者也可以使用__attribute__((weak))显式声明一个符号为弱符号。

如果两个符号同名,一个是强符号一个是弱符号,编译器会怎么处理?

如果两个符号都是强符号,编译器会报重复定义错误;如果一个是强符号一个是弱符号,编译器会选择强符号的值;如果两个都是弱符号,编译器会选择占用空间较大的符号,以避免溢出、越界等严重后果。

强引用和弱引用有什么区别?弱引用在链接时有什么特点?

强引用要求符号必须有定义,否则链接时会报undefined reference错误;弱引用则允许符号未定义,如果未定义,引用处的值为0,链接不会报错。弱引用使用__attribute__((weakref))声明,但现代编译系统中需要配合alias属性使用。

弱符号和弱引用在库开发中有什么实际用途?

在库的实现中,弱符号允许用户自定义扩展功能的函数来覆盖库中的弱符号函数;弱引用允许库将某些扩展功能函数定义为弱引用,用户需要时定义并链接,不需要时链接也不会报错,从而方便地裁剪和组合库的功能。

强符号和弱符号是C标准的一部分吗?其他编译器支持吗?

不是,C标准里根本没有提到强符号和弱符号,这只是GCC实现定义的特性,MS C编译器不支持这个概念。

使用__attribute__((weak))将已初始化的全局变量声明为弱符号后,还能和同名的强符号共存吗?

不能。使用__attribute__((weak))将强符号转换为弱符号后,不能与一个强符号共存,否则编译器会报重复定义错误。例如int __attribute__((weak)) x = 0; int x = 1; 会报错。

🏷️

标签

➡️

继续阅读