Why Were @, $, and ` Excluded from C89's Basic Source Character Set? (And Added in C23)
If you have ever dug into the early ANSI/ISO C standards, you might have noticed a curious omission: characters like the commercial at (@), the dollar sign ($), and the backtick (`) were completely absent from C89's basic source character set. This omission persisted through C99 and C11, only to finally be reversed decades later in C23.
The Core Reason: ISO 646 and International Character Sets
The primary reason for excluding @, $, and ` from the C89 basic source character set comes down to international portability in the late 1980s—specifically the limitations of ISO/IEC 646 (and older national character standards).
While standard ASCII is a 7-bit character encoding where positions 0x24 ($), 0x40 (@), and 0x60 (`) are fixed, the international standard ISO 646:1983 defined several "national-use" code points:
0x24was commonly replaced by national currency signs like£(Pound) or¥(Yen).0x40and0x60were designated as variable/national characters, often mapped to accented letters (such asà,§,Ä, oré) on European terminal keyboards.- Characters like
{,},[,],|, and~were also variable in ISO 646, which is precisely why C89 introduced trigraphs (e.g.,??(for[) to ensure C could be written on non-ASCII keyboards.
The ANSI X3J11 and ISO WG14 committees wanted the C language's basic source character set to be invariant across all international variants of ISO 646. Since @, $, and ` were not needed for C's core syntax and were known to vary across terminals, they were omitted to prevent compilation errors and character corruption on international systems.
The C99 Universal Character Name (UCN) Carve-Out
When C99 introduced Universal Character Names (UCNs) like \u00A9 to represent extended Unicode identifiers and strings, it banned UCNs representing control codes and basic characters (under 0x00A0). However, the standard explicitly made an exception:
// C99 / C11 rule: UCN cannot specify characters < 00A0
// EXCEPT for 0024 ($), 0040 (@), or 0060 (`)Why this exception? Because these three characters were not part of the basic character set, standardizing UCN references to them (e.g., \u0024) allowed implementations to use them in identifiers or extended character literals across platforms without violating the invariant basic character set rules.
The Accidental Appearance of @ in C89 Examples
Interestingly, the @ character appears inside string literals in the standard's non-normative examples (such as in C89 section 3.8.3.5 / C99 section 6.10.3.5):
fputs("strncmp(\"abc\\0d\", \"abc\", '\\4') == 0" ": @\n", s);This is because the standard permitted implementations to include extended execution characters in string literals, provided the core grammar didn't depend on them. The committee simply used an ASCII-based environment when drafting example code snippets.
Why C23 Finally Added Them Back
With the release of C23 (ISO/IEC 9899:2024), ISO WG14 modernized the character set requirements. Because virtually all modern computing infrastructure now standardizes on UTF-8 and ASCII-compatible encodings, the ISO 646 limitations of the 1980s are no longer a practical concern.
As a result, C23 formally deprecated trigraphs and included $, @, and ` directly into the basic character set, aligning the language with modern development environments and multi-language interoperability requirements.