Getting silly with C, part (void*)2
C’s quirky and often confusing edge cases—such as odd parsing ambiguities, GNU-only extensions, and array/pointer tricks—are used here to probe whether C is really “simple” or just small and overloaded with historical baggage. Commenters debate proposals for stripped‑down or alternative languages (from “micro‑C” to Zig, Rust, D, Forth, and even WebAssembly) that avoid undefined behavior and fragile syntax while still targeting low-level, portable code. Others argue that many of C’s pitfalls are mitigated by modern compilers and coding conventions, and that its flexibility and expressiveness still justify its continued use despite its sharp edges.
Minimal / “micro C” vs. existing languages
- Several commenters argue C syntax is too rich and error‑prone; propose a stripped-down “micro C”:
- No implicit casts (except literals,
void*), only fixed-width types, one loop construct, noswitch/enum/generics, fewer operators, real compile‑time constants. - Inline support for atomics, memory barriers, endianness.
- No implicit casts (except literals,
- Counterpoints:
- This starts looking like “assembly with sugar”; others say that’s not automatically bad if typed/structured.
- Some suggest WebAssembly, unsafe Rust, Forth, or Zig as better targets/alternatives; debate on runtime requirements and portability.
- There’s mention of C0 (teaching subset of C) and D as examples of “cleaner C-like” designs.
GNU C extensions and upcoming C features
- The article’s tricks lean heavily on GNU C:
- Compound literals and designated initializers (e.g., “BASIC-like” indexed array initialization).
- Case ranges in
switch(possibly coming to C2y). - Forward parameter declarations: seen as “insane but fun,” debated usefulness vs complexity, and their status in the standards process is contested/unclear.
- Some discussion on variable-length arrays, incomplete structs with trailing flex arrays, and attributes like
[[counted_by()]]as safety aids.
C’s quirks, parsing ambiguities, and readability
- Many examples show that without declaration info, constructs like
(A)(B)orA(B)are ambiguous (type vs function). - Discussion of
3[array]being valid due to array indexing being defined as*(a + b). - Classic error patterns like
for (...) ;are seen as “junk DNA” that should be removed; others argue modern compilers already warn effectively. - There is tension between:
- Viewing C as a small, flexible notation that inevitably allows unreadable “gibberish.”
- Viewing its edge cases as needless traps kept only for backward compatibility and obfuscation contests.
Undefined behavior and safety
- One side dramatizes undefined behavior as allowing arbitrary outcomes, emphasizing its danger.
- Others clarify UB as “no requirements from the standard,” not magical powers for compilers or malware, but still hazardous because compilers need not warn.
- Some argue compilers and sanitizers (UBSan, bounds-safety options) can mitigate UB in practice.
Broader reflections on C’s legacy
- Mixed feelings: from “erase all C code” hyperbole to defenses of C’s historical role replacing assembly and enabling OS kernels.
- C is characterized as:
- Small but not simple.
- Powerful for expressing complex things concisely.
- Burdened with ergonomics and safety pitfalls that newer languages try to address.