2025-10-19

possibly useful features missing in c

part of c programming

miscellaneous

  • direct literal initialization of dynamically allocated arrays

    • int* a = malloc(3 * sizeof(int)); a = {1, 2, 3}; is invalid
    • requires a temporary and copy or a compound literal plus memcpy
  • keyword arguments

    • no native keyword-argument syntax
    • optional parameters require sentinels, structs, or variadics
  • parametric array types

    • typedef int a3[3]; works for fixed length
    • no way to name "array of n" with n as a value parameter
  • local symbolic bindings

    • only block variables exist
    • macros do not shadow and are global to the translation unit
  • literal symbols: no symbol type distinct from strings or enums
  • exact rationals: no built-in fractional type like 14/3
  • reflection and type inference

    • no runtime type info
    • _Generic gives limited compile-time dispatch
    • typeof is nonstandard
  • portable include guard primitive

    • only #ifndef/#define pattern is standard
    • #pragma once is widespread but nonstandard
  • anonymous functions

    • standard c has no anonymous or nested functions
    • gcc nested functions are nonportable
    • function pointers refer to named functions only
  • variadics

    • type metadata: each argument should carry its real type and size so the callee can validate or cast correctly.

    • count metadata: the callee should know how many arguments exist.

    • consistent layout: arguments stored in a contiguous, well-defined block so they can be iterated or copied safely.

namespaces

  • c exposes file-scope identifiers to the whole translation unit
  • included headers cannot hide internal helpers except via static
  • collisions are common without prefixes
  • no renaming or aliasing at inclusion time
  • typical workarounds

    • prefix all exported identifiers
    • static for internal linkage
    • build separate objects + headers; export a narrow api
    • tool-based rewriting or modules (e.g., clang modules)
  • a language-level namespace facility would allow encapsulation without linker indirection

memory ownership semantics

  • no built-in lifetime or ownership tracking
  • manual acquire/release across calls is error-prone
  • explicit lifetime constructs or ownership transfer syntax would reduce leaks and dangling pointers
  • see: rust ownership model

preprocessor features

  • variadics and repetition

    • __VA_COUNT__ (portable argument count)
    • repetition primitives: for_each, map, with separator control
    • __VA_OPT__ everywhere, including nested use (c23 defines it; clarify nesting)
  • structure-aware matching

    • balanced-group patterns for (...) [...] {...}
    • emptiness and arity dispatch tied to those groups
  • macro scoping and hygiene

    • block-scoped macros (standardize push/pop of macro state)
    • optional fresh identifier primitive (unique_id)
    • statement macros to avoid do { } while (0) idiom
  • directives and phase control

    • allow conditional preprocessing constructs inside replacement lists with defined re-scan rules
    • controlled generation of directives (for example, late-phase #include)
    • explicit expansion control: expand-once, depth limits, and a no-expand marker
  • introspection and diagnostics

    • standard predicates usable in expressions: is-defined and equals
    • macro traits: is_macro(name), macro_arity(name)
    • formatted diagnostics: #errorf with location info