I write type-safe generic data structures in C

Technique and Overall Reception

  • Core idea discussed: use a union field plus typeof (or compiler extensions) so a generic list “handle” carries element type information, with type safety enforced via function pointer types or dummy assignments.
  • Many commenters find the trick clever and potentially useful, especially because the macros expand to normal functions that are debuggable and don’t impose per-element runtime overhead.
  • Others feel it’s too complex for everyday use and prefer more conventional macro-based generics or just switching to C++.

Intrusive Data Structures and Unions

  • Several people note the approach fits non-intrusive containers (e.g., lists where nodes point to data), but intrusive structures (node embedded in user struct, possibly multiple containers per object) are harder to express this way.
  • For intrusive structures, commenters often rely on macro-heavy wrappers or Linux-kernel-style embedded list nodes, sometimes erasing types intentionally and accepting runtime checks or casts.

Compiler, C23, and typeof Issues

  • Discussion of C23’s structural type equivalence for tagged unions: it helps but only when union tags and layouts match; generating unique tags per instantiation is nontrivial for complex types.
  • Long side-thread on typeof in MSVC: when it appeared, differences in semantics, and bugs/limitations (e.g., function-pointer typeof not working as documented).
  • Some criticize function-pointer casting as relying on non-guaranteed pointer representation and potentially breaking aliasing analysis.

Correctness and Practical Limitations

  • Technical critiques: alignment and padding concerns with uint64_t data[]; strict aliasing violations; macro variants that inadvertently overwrite list heads; inability to return values from certain macro forms; double evaluation of arguments.
  • Concerns that relying on UB-sensitive tricks and aliasing subtleties undermines robustness, even if compilers usually “optimize it away.”

Alternative Approaches to Generics in C

  • Widely used alternative: “pseudo-templates” via header macros that generate type-specialized structs and functions per instantiation, trading boilerplate for straightforward codegen and optimization.
  • Other schemes: function-pointer–based type carriers; external vtables with forward declarations; intrusive list patterns; elaborate code generators and custom header languages.
  • Some argue that for many programs, hand-written, use-case-specific structures (often arrays) suffice and avoid generic complexity.

Why Not Just Use C++ or Another Language?

  • Many suggest C++ templates (or D, Rust) as cleaner solutions with language support.
  • Counterpoints: entrenched C codebases, embedded targets with limited toolchains, safety/certification constraints, and projects or extension APIs that are “C-only.”
  • Philosophical split: some see advanced macro tricks as overengineering; others view them as pragmatic tools when C is mandated.