在C语言中,编译器将没有初始化的全局变量定义作为弱符号处理,将初始化的全局变量定义作为强符号处理。在链接的时候不允许多个相同的强符号出现,但是允许一个强符号和多个弱符号同时出现,或者只有多个弱符号。
但是在C++中,为了维护单定义原则,初始化和未初始化的全局变量都会被当成强符号对待。
| 强符号 | 弱符号 | |
|---|---|---|
| C | 初始化的全局变量定义 | 未初始化的全局变量定义 |
| C++ | 初始化或未初始化的全局变量定义 | 显示定义 __ attribute __ ((weak)) |
| 强符号 | 弱符号 | |
|---|---|---|
| 强符号 | 不允许多个相同强符号同时存在 | 允许一个强符号和多个弱符号同时存在 |
| 弱符号 | 允许一个强符号和多个弱符号同时存在 | 允许多个弱符号同时存在,但是最终链接器会选择占空间最大的那个 |
下面着重介绍一下C++中弱符号的使用方法和应用场景:
使用方法
1. 错误使用-未显示声明弱符号
cpp
//--------------main.cpp-----------------
#include <iostream>
int var_strong = 1;
int main()
{
std::cout << var_strong << std::endl;
return 0;
}
//---------------------------------------
//--------------other.cpp----------------
double var_strong = 4.0;
//---------------------------------------
bash
cmake_minimum_required(VERSION 3.10)
Project(Modern)
add_executable(Modern src/main.cpp src/other.cpp)
构建过程中会出现链接器报错-重复定义 ,因为C++中将这两个var_strong 都看成了强符号。

2. 正确使用-显示声明弱符号
cpp
//--------------main.cpp-----------------
#include <iostream>
int var_strong = 1;
int main()
{
std::cout << var_strong << std::endl;
return 0;
}
//---------------------------------------
//--------------other.cpp----------------
int var_strong __attribute__((weak))= 4;
//---------------------------------------
应用场景
相比现代C++,使用弱符号会减少运行时的选择耗时。
1. 需要零开销运行时的嵌入式系统
cpp
// 链接脚本中常用
__attribute__((weak, alias("default_handler")))
void UART_IRQHandler(void);
// 用户可选覆盖
void UART_IRQHandler(void) __attribute__((alias("my_uart_handler")));
2. 编译器/工具链内部
cpp
// 工具链提供的默认new/delete处理
__attribute__((weak))
void* operator new(std::size_t size) {
if (void* ptr = std::malloc(size)) return ptr;
throw std::bad_alloc();
}
3. 跨平台抽象层
cpp
// platform_abstraction.h
__attribute__((weak))
void platform_specific_function();
// 平台实现1
void platform_specific_function() { /* Linux实现 */ }
// 平台实现2(不同文件)
void platform_specific_function() { /* Windows实现 */ }