GCC 8.4.0下C与C++强符号、弱符号处理机制差异及链接报错问题咨询
Great question! The root cause lies in different handling of uninitialized global variables between C and C++ standards, which affects how the linker treats their symbols (strong vs. tentative/weak). Let's break this down step by step:
Background: Linker Symbol Rules
First, let's recap the rules you noted to set context:
- Multiple strong symbols with the same name → Linker error (duplicate definition)
- One strong symbol + one/multiple weak symbols → Linker picks the strong symbol
- Only weak symbols with the same name → Linker picks one arbitrarily
What's the Difference Between C and C++ Here?
The key is how each language treats the line int gvar; (uninitialized global variable):
1. In C (.c files)
C has a concept called tentative definitions. A global variable declared without an initializer (like int gvar; in main.c) falls into this category. Here's what happens:
- The linker merges all tentative definitions of the same variable into a single entry.
- If there's an external definition (like
int gvar = 111;inaux.c) with an explicit initializer, that becomes the authoritative definition, and all tentative definitions resolve to it.
So when compiling .c files, GCC treats main.c's gvar as a tentative definition, and aux.c's as a strong external definition. They merge cleanly without errors, and the final executable uses the value 111.
2. In C++ (.cpp files)
C++ does not recognize tentative definitions. Any global variable declaration without the extern keyword is a full, strong definition—even if it's uninitialized. Here's why:
int gvar;in C++ is implicitly zero-initialized. This counts as a complete definition that allocates storage for the variable, marking it as a strong symbol.int gvar = 111;inaux.cppis also a strong symbol (with an explicit initializer).
With two strong symbols named gvar, the linker hits the "multiple strong symbols" rule and throws the duplicate definition error you encountered.
How to Fix the C++ Case?
If you want the C++ code to link successfully, modify the declaration in main.cpp to a non-defining declaration using extern:
// main.cpp #include <stdio.h> extern int gvar; // Declare, don't define gvar int main(){ printf("shared var is %d\n",gvar); return 0; }
Now only aux.cpp holds a strong definition of gvar, so the linker resolves the reference in main.cpp to it, and the program will output shared var is 111.
Note on GCC Version
Your GCC 8.4.0 behaves consistently with C and C++ standards here—this isn't a version-specific quirk, but a fundamental difference between the two languages.
内容的提问来源于stack exchange,提问作者WilliamAllwaysWin

