Maximal min() and max()
Macro complexity and compile-time blowups
- Original topic: Linux kernel
min/maxmacros exploding to tens of megabytes of generated C, slowing compilation. - Several commenters share similar experiences: sophisticated “safe arithmetic” or comparison macros can expand to GB-sized translation units or crash compilers.
- The core cause: heavy preprocessor use to emulate generics and type checks, leading to exponential macro expansion in nested calls (e.g.,
min(min(a,b),c)).
Why macros instead of functions?
- Macros work in constant-expression contexts (e.g., array sizes); C lacks
constexpr-style functions. - C has no true type-generic functions; C11
_Generichelps but still requires macros for dispatch and doesn’t naturally support mixed-type comparisons. - The kernel wants type-safe
min/maxthat:- Work with mixed integer types.
- Detect unsafe implicit conversions.
- Preserve constant-expression usability.
Type system, implicit conversions, and safety
- Many argue that C’s implicit numeric conversions are a fundamental design flaw that force these macro contortions.
- Comparisons with Rust and Haskell: explicit casts preferred; fewer “magic” promotions.
- C++ is criticized for adding even more implicit-conversion paths, though it can disable them for user types.
C vs C++ vs Rust (and other languages)
- Some say the macro mess illustrates C’s limitations and argue for languages with real generics and hygienic macros.
- Others respond that switching a massive kernel codebase to another language for “better
min/max” is unrealistic. - C++ is debated:
- Pro: templates and
constexprcould express safemin/maxmore cleanly. - Con: incompatibilities with C99 features, template compile-time costs, extra UB “landmines”, and social/maintenance concerns.
- Pro: templates and
- Rust is seen as more purpose-built for kernels, but its dependency culture, macros, and compile times draw criticism.
Alternatives proposed
- Define per-type
min_*/max_*functions or macros; pushback: weakenstypedefusability and doesn’t solve mixed-type safety. - Use
_Genericplus GNUtypeofto dispatch to typed inline functions; still complex and may not fix constant-expression needs or expansion size. - Add compiler builtins or even standard-library
min/maxthat handle type safety and constant contexts; some see this as the cleanest long-term solution, but it doesn’t help older compilers.
Meta-discussion on language and tooling design
- The issue is used as an example of:
- How much work C programmers do to avoid higher-level language features.
- How better macro systems (hygienic, AST-level) or DSLs could avoid textual blowups.
- How large, conservative projects incrementally evolve via compiler extensions rather than language swaps.