Panel For Example Panel For Example Panel For Example

Weak Symbols and Weak References in Embedded C

Author : Adrian September 16, 2025

GNU C __attribute__

Overview of __attribute__

__attribute__ is a compiler directive provided by GNU C. It allows the programmer to attach attributes to declarations, which are used by the compiler during compilation for additional checks and optimizations. It can be applied to variables, functions, parameters, methods, and types in C, C++, and Objective-C.

Benefits of using __attribute__

  • Provides context to the compiler to enable optimizations; correct use can yield noticeable improvements.
  • Causes the compiler to emit additional warnings, helping to make the code more consistent.
  • Serves as documentation for readers, clarifying the author’s intent.

Incorrect use of __attribute__ can provide misleading context to the compiler and lead to hard-to-find errors.

Strong and Weak Symbols

In standard C many programmers assume that defining the same variable or function multiple times in the same scope is always an error. GCC extends the standard by distinguishing between strong and weak symbols. During compilation, variables and functions are represented as symbols; some are considered strong and others weak.

By default, the compiler treats functions and initialized global variables as strong symbols, and uninitialized global variables as weak symbols. If the programmer does not explicitly specify, the compiler applies these defaults. A symbol can be explicitly declared weak using __attribute__((weak)).

When two definitions of the same symbol appear, and at least one is weak, the linker follows these rules:

  • If both are strong symbols, the linker reports an error: redeclaration of 'name'.
  • If one is strong and the other is weak, the strong symbol is chosen.
  • If both are weak, the symbol with the larger size is chosen, which helps avoid issues such as overflow or out-of-bounds problems.

With the default symbol types, strong and weak symbols can coexist. For example:

int x; int x = 1;

The compilation succeeds and x will have the value 1.

However, marking a symbol weak does not allow it to coexist with a strong definition of the same symbol. For example:

int __attribute__((weak)) x = 0; int x = 1;

The linker will report a redefinition error.

Strong and Weak References

GCC also supports weak references. The compiler compiles source files to object files, and the linker resolves symbols across object files. By default, references to symbols are strong, but a programmer can declare a weak reference with __attribute__((weakref)). Note that this declares a reference, not a definition; it indicates that the symbol may be defined in another module.

For example, a function can be declared as:

__attribute__((weakref)) void func(void);

If code calls func(), and func is not defined in the linked modules, the symbol resolves to NULL (zero). If func is defined elsewhere, the call invokes that implementation. A typical pattern is:

__attribute__((weakref)) void func(void); void main(void) { if (func) { func(); } }

Modern toolchains, however, may warn that weakref should be accompanied by an alias attribute:

warning: 'weakref' attribute should be accompanied with an 'alias' attribute [-Wattributes]

Use Cases in Libraries

Weak symbols and weak references are useful in library design. A library can provide default implementations as weak symbols that users can override by providing their own definitions. Optional extensions can be declared as weak references; if the user links a module that defines the extension, it will be used, otherwise the linker will not report an error. This enables flexible composition and optional functionality in libraries.

Notes

The C standard does not define strong or weak symbols; this is a GCC implementation detail. Other compilers, such as Microsoft Visual C, do not use the same concept.