Weak Symbols vs Strong Symbols : When working with C programming, especially in embedded systems or system-level development, you will often encounter the concepts of weak symbols and strong symbols. These terms come into play during the linking stage of compilation. Understanding them is crucial for writing flexible, modular, and maintainable code.
In this article, we’ll explore the difference between weak symbols and strong symbols in C, how they work, and where they are used.
What is a Weak symbol and Strong Symbols in C ?
In C programming, symbols represent functions or variables that the linker resolves during compilation. Strong symbols are the default definitions of global variables or functions, and only one strong symbol with the same name can exist across a program. If multiple strong symbols are present, the linker throws a multiple-definition error.
On the other hand, weak symbols are declared using the __attribute__((weak)) attribute. They act as fallback definitions, meaning if a strong symbol with the same name is available, it overrides the weak symbol. If no strong definition exists, the weak symbol is used.
This mechanism is particularly useful in embedded systems, libraries, and modular applications, where weak symbols provide default implementations (such as interrupt handlers or library functions) that can be optionally overridden by the developer.
Key difference:
- Strong symbols = Default and unique definitions.
- Weak symbols = Flexible fallback definitions, overridden by strong symbols if available.
What are Symbols in C?
In simple terms, a symbol is the name that represents a function or variable in your program. For example:
int myVar = 10; // 'myVar' is a symbol
void myFunction() {} // 'myFunction' is a symbol
When you compile your code, the compiler generates object files with these symbols. The linker then resolves them to produce the final executable.
Strong symbols in C
A strong symbol is the default type of symbol generated by the compiler when you define a global variable or function.
👉 Characteristics of strong symbols:
- Created when you define a function or variable without the
weakattribute. - Only one definition of a strong symbol can exist across the program.
- If two strong symbols with the same name are defined in different files, the linker will throw an error (multiple definition error).
Example of Strong Symbol
int data = 100; // Strong symbol by default
void printData() {
printf("%d\n", data);
}
Here, data and printData are strong symbols.
Weak Symbols in C
A weak symbol is a symbol that tells the linker:
“Use this symbol if no strong definition is found, otherwise ignore me.”
👉 Characteristics of weak symbols:
- Declared using the
__attribute__((weak))keyword. - Can be overridden by a strong symbol with the same name.
- If no strong symbol is provided, the weak symbol is used as a fallback.
Example of Weak Symbol
__attribute__((weak)) void myFunction() {
printf("Default weak function\n");
}
If another file defines a strong version of myFunction, the weak version will be ignored by the linker.
Weak vs Strong Symbols in C
| Feature | Strong Symbol | Weak Symbol |
|---|---|---|
| Default behavior | Yes | No (explicitly defined) |
| Multiple definitions | Not allowed (linker error) | Allowed, but overridden by strong |
| Use case | Normal variables/functions | Fallbacks, optional overrides |
| Example use | int var = 10; | __attribute__((weak)) void func() |
Why Use Weak Symbols?
Weak symbols are very useful in system programming and embedded systems:
- Fallback Implementation
- Provide a default implementation of a function.
- Example: weak logging functions can be overridden by user-defined strong ones.
- Flexibility in Libraries
- Library authors often define weak symbols so developers can override them with custom implementations.
- Bootloaders & Firmware
- In embedded systems, weak symbols are used for interrupt handlers or startup code, which can later be overridden by user-defined handlers.
Practical Example – Weak vs Strong
// weak_function.c
#include <stdio.h>
__attribute__((weak)) void hello() {
printf("Hello from weak function!\n");
}
// strong_function.c
#include <stdio.h>
void hello() {
printf("Hello from strong function!\n");
}
// main.c
int main() {
hello();
return 0;
}
👉 If you compile all three files together:
- Output will be: “Hello from strong function!”
- The weak symbol is ignored because a strong definition exists.
👉 If you compile without strong_function.c:
- Output will be: “Hello from weak function!”
This demonstrates the priority of strong symbols over weak symbols.
Weak Symbols vs Strong Symbols
In C programming, symbols are names that represent functions or variables during the compilation and linking stages. The linker decides how these symbols are resolved. Based on their definition, they can be classified as strong symbols or weak symbols.
Strong Symbols in C
- Definition: Default symbols created when you define a global variable or function normally.
- Characteristics:
- Only one strong symbol with the same name can exist.
- If multiple strong symbols are defined → linker error.
- Used for actual, unique implementations.
- Example:
int count = 0; // Strong symbol void myFunction() { } // Strong symbol
Weak Symbols in C
- Definition: Symbols explicitly marked as weak using
__attribute__((weak)). - Characteristics:
- Can be overridden by a strong symbol with the same name.
- If no strong symbol exists, the weak symbol is used.
- Provide default/fallback implementations.
- Example:
__attribute__((weak)) void handler() { printf("Default weak handler\n"); }
Key Differences Between Weak and Strong Symbols
| Aspect | Strong Symbol | Weak Symbol |
|---|---|---|
| Definition | Default function/variable definition | Defined using __attribute__((weak)) |
| Multiplicity | Only one allowed | Multiple allowed (overridden if strong exists) |
| Priority | Always preferred by linker | Used only if strong symbol not found |
| Error Handling | Multiple definitions → Linker error | No error, just overridden |
| Use Case | Unique implementation of code | Fallbacks, library defaults, embedded handlers |
Example Demonstrating Weak vs Strong
// weak.c
#include <stdio.h>
__attribute__((weak)) void hello() {
printf("Hello from weak function\n");
}
// strong.c
#include <stdio.h>
void hello() {
printf("Hello from strong function\n");
}
// main.c
int main() {
hello();
return 0;
}
👉 If all files are compiled → “Hello from strong function”
👉 If strong.c is not compiled → “Hello from weak function
Advantages of Weak and Strong Symbols
Advantages of Strong Symbols
- Ensure uniqueness of functions and variables across the program.
- Prevent accidental multiple definitions through linker checks.
- Provide clear ownership of implementation (no ambiguity).
Advantages of Weak Symbols
- Allow default implementations that can be overridden.
- Useful for library development – provides flexibility to end-users.
- Helpful in embedded systems for fallback code like interrupt handlers.
- Enable code modularity and easy customization without changing base code.
Disadvantages of Weak and Strong Symbols
Disadvantages of Strong Symbols
- Multiple definitions lead to linker errors.
- Not flexible – you cannot provide optional overrides.
Disadvantages of Weak Symbols
- Can cause unintended overrides if strong symbols are accidentally defined.
- Harder to debug, since weak definitions may silently get replaced.
- May lead to inconsistent behavior if not properly documented.
Real-Time Applications of Weak and Strong Symbols
- Embedded Systems (Microcontrollers & Firmware)
- Startup code often defines weak interrupt handlers.
- Developers can override them with strong custom handlers.
- Operating Systems and Libraries
- System libraries provide weak functions as placeholders, allowing developers to replace them with optimized implementations.
- Bootloaders
- Weak symbols act as default functions for initialization routines, overridden later by board-specific implementations.
- Driver Development
- Hardware drivers may use weak functions to allow custom extensions without modifying the core code.
- Logging and Debugging Systems
- A weak logging function may be defined in a library, which can be overridden by a strong symbol to implement device-specific logging.
Key Takeaways of weak and strong symbols in C
- Strong symbols are the default; they must be unique across your program.
- Weak symbols act as placeholders or fallback implementations.
- If both exist, the strong symbol overrides the weak symbol.
- Useful in embedded systems, libraries, and modular applications where flexibility and default behavior are important.
FAQ of Weak and Strong symbols in C
1.What is a weak symbol in C programming?
__attribute__((weak)). It provides a default implementation that can be overridden by a strong symbol if available.2.What is a strong symbol in C programming?
3.How does the linker resolve weak and strong symbols in C?
4.Why are weak symbols used in embedded systems?
5.Weak vs strong symbols in embedded C examples
6.Advantages and disadvantages of weak symbols in C
Advantages: Provide fallback functions, flexibility in libraries, easy overrides, useful in firmware and drivers.
Disadvantages: Can be accidentally overridden, harder to debug, and may cause inconsistent behavior if not documented.
7.Real-time applications of weak symbols in embedded systems
a) Interrupt handlers in microcontrollers
b) Default startup code in bootloaders
c) System libraries providing optional implementations
d) Logging/debugging placeholders overridden by user code
8.How to override weak functions in C
9.Weak attribute in GCC explained
__attribute__((weak)) keyword is used to declare a symbol as weak. This tells the linker to treat it as a fallback definition, which can be replaced if a strong definition exists.1.What is a weak symbol in C?
A weak symbol in C is a function or variable marked with __attribute__((weak)). It can be overridden by a strong definition if available.
2.What is a strong symbol in C?
A strong symbol is the default type of global function or variable in C. Only one strong symbol of the same name can exist; otherwise, the linker throws a multiple definition error.
3.What happens if both weak and strong symbols exist in C?
The strong symbol takes precedence, and the weak symbol is ignored by the linker.
4.Why are weak symbols used in embedded systems?
Weak symbols allow developers to provide default implementations (e.g., interrupt handlers) which can later be overridden by user-defined strong implementations.
5.Can two strong symbols exist with the same name?
No, multiple strong symbols with the same name cause a linker error.
You can also Visit other tutorials of Embedded Prep
- Multithreading in C++
- Multithreading Interview Questions
- Multithreading in Operating System
- Multithreading in Java
- POSIX Threads pthread Beginner’s Guide in C/C++
- Speed Up Code using Multithreading
- Limitations of Multithreading
- Common Issues in Multithreading
- Multithreading Program with One Thread for Addition and One for Multiplication
- Advantage of Multithreading
- Disadvantages of Multithreading
- Applications of Multithreading: How Multithreading Makes Modern Software Faster and Smarter”
- Master CAN Bus Interview Questions 2025
- What Does CAN Stand For in CAN Bus?
- CAN Bus Message Filtering Explained
- CAN Bus Communication Between Nodes With Different Bit Rates
- How Does CAN Bus Handle Message Collisions
- Message Priority Using Identifiers in CAN Protocol


Leave a Reply