Weak Symbols vs Strong Symbols
, , , , , ,

Weak Symbols vs Strong Symbols in C | Master Embedded Interview Preparation (2025)

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 weak attribute.
  • 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

FeatureStrong SymbolWeak Symbol
Default behaviorYesNo (explicitly defined)
Multiple definitionsNot allowed (linker error)Allowed, but overridden by strong
Use caseNormal variables/functionsFallbacks, optional overrides
Example useint var = 10;__attribute__((weak)) void func()

Why Use Weak Symbols?

Weak symbols are very useful in system programming and embedded systems:

  1. Fallback Implementation
    • Provide a default implementation of a function.
    • Example: weak logging functions can be overridden by user-defined strong ones.
  2. Flexibility in Libraries
    • Library authors often define weak symbols so developers can override them with custom implementations.
  3. 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

AspectStrong SymbolWeak Symbol
DefinitionDefault function/variable definitionDefined using __attribute__((weak))
MultiplicityOnly one allowedMultiple allowed (overridden if strong exists)
PriorityAlways preferred by linkerUsed only if strong symbol not found
Error HandlingMultiple definitions → Linker errorNo error, just overridden
Use CaseUnique implementation of codeFallbacks, 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

  1. Embedded Systems (Microcontrollers & Firmware)
    • Startup code often defines weak interrupt handlers.
    • Developers can override them with strong custom handlers.
  2. Operating Systems and Libraries
    • System libraries provide weak functions as placeholders, allowing developers to replace them with optimized implementations.
  3. Bootloaders
    • Weak symbols act as default functions for initialization routines, overridden later by board-specific implementations.
  4. Driver Development
    • Hardware drivers may use weak functions to allow custom extensions without modifying the core code.
  5. 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?

Ans: A weak symbol in C is a function or variable marked with __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?

Ans: A strong symbol is the default definition of a global function or variable in C. Only one strong symbol with the same name can exist; otherwise, the linker reports a multiple-definition error.

3.How does the linker resolve weak and strong symbols in C?

Ans: The linker always gives priority to strong symbols. If both weak and strong symbols of the same name exist, the strong one overrides the weak one. If no strong symbol is found, the weak symbol is used.

4.Why are weak symbols used in embedded systems?

Ans: Weak symbols are widely used in embedded systems to provide default implementations of functions, such as interrupt handlers or startup code, which can later be overridden with strong custom implementations.

5.Weak vs strong symbols in embedded C examples

Ans: For example, in an embedded project, a library might provide a weak function for logging, while the developer can define a strong logging function to customize it. If the strong symbol is defined, it overrides the weak one.

6.Advantages and disadvantages of weak symbols in C

Ans:
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

Ans:
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

Ans: To override a weak function, simply define a strong function with the same name in your program. The linker will ignore the weak definition and use the strong one.

9.Weak attribute in GCC explained

Ans: In GCC, the __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.

Weak Symbols vs Strong Symbols
Weak Symbols vs Strong Symbols

Leave a Reply

Your email address will not be published. Required fields are marked *