Take this code:
int main(void)
{
int var$ = 3;
printf("%d\n",var$);
}
This compiles properly (GCC, Clang, MSVC) and prints 3
upon execution as expected.
However, this code:
int main(void)
{
int var@ = 8;
printf("%d\n",var@);
}
This does not compile (GCC, Clang, MSVC), with the error stray '@' in program
.
Looking at the C/C++ Operator List (Ctrl+F'ing for @
and $
), neither of them are operators.
Why is var$
valid but var@
isn't?
Taking a look at the C11 Specification, Section 6.4.2 on Identifiers:
Semantics
2 An identifier is a sequence of nondigit characters (including the underscore
_
, the lowercase and uppercase Latin letters, and other characters) and digits, which designates one or more entities as described in 6.2.1. Lowercase and uppercase letters are distinct. There is no specific limit on the maximum length of an identifier.3 Each universal character name in an identifier shall designate a character whose encoding in ISO/IEC 10646 falls into one of the ranges specified in D.1.71) The initial character shall not be a universal character name designating a character whose encoding falls into one of the ranges specified in D.2. An implementation may allow multibyte characters that are not part of the basic source character set to appear in identifiers; which characters and their correspondence to universal character names is implementation-defined.
(emphasis mine)
And per the GCC Manual on Implementation-defined behavior:
- Identifier characters.
The C and C++ standards allow identifiers to be composed of ‘
_
’ and the alphanumeric characters. C++ also allows universal character names. C99 and later C standards permit both universal character names and implementation-defined characters.GCC allows the ‘
$
’ character in identifiers as an extension for most targets. This is true regardless of thestd=
switch, since this extension cannot conflict with standards-conforming programs. When preprocessing assembler, however, dollars are not identifier characters by default.
(emphasis mine)
And again in Tokenization, and mentioned in Idav1s's answer:
As an extension, GCC treats ‘
$
’ as a letter. This is for compatibility with some systems, such as VMS, where ‘$
’ is commonly used in system-defined function and object names. ‘$
’ is not a letter in strictly conforming mode, or if you specify the-$
option.
Because VMS used many system-defined functions and objects that were named with $
, GCC allowed $
to be included as an implementation-specific character for compatibility on some systems.
Special characters such as $
and @
aren't explicitly allowed by C specification to be in an identifier, but certain characters (such as $
here) may be allowed by implementation. GCC, for example allows $
in identifiers for most targets. The same goes for Clang (as most of its implementation-defined behavior is the same as GCC), and MSVC.