Почему var$ компилируется, а var@ нет?
Возьми этот код:
int main(void)
{
int var$ = 3;
printf("%d\n",var$);
}
Это правильно компилируется ( GCC, Clang, MSVC) и печатает 3
после исполнения, как ожидалось.
Тем не менее, этот код:
int main(void)
{
int var@ = 8;
printf("%d\n",var@);
}
Это не компилируется ( GCC, Clang, MSVC), с ошибкой stray '@' in program
,
Просмотр списка операторов C/C++ (Ctrl + F'для @
а также $
), ни один из них не является оператором.
Почему var$
действительный но var@
нет?
3 ответа
Взгляните на спецификацию C11, раздел 6.4.2 по идентификаторам:
Семантика
2 Идентификатор - это последовательность нецифровых символов (включая подчеркивание
_
, строчные и заглавные латинские буквы и другие символы) и цифры, которые обозначают одну или несколько сущностей, как описано в 6.2.1. Строчные и прописные буквы различны. Не существует конкретного ограничения на максимальную длину идентификатора.3 Каждое универсальное имя символа в идентификаторе должно обозначать символ, кодировка которого в ИСО / МЭК 10646 попадает в один из диапазонов, указанных в D.1.71) Начальный символ не должен быть универсальным именем символа, обозначающим символ, кодировка которого попадает в один из диапазонов, указанных в D.2. Реализация может позволить многобайтовым символам, которые не являются частью основного исходного набора символов, появляться в идентификаторах; какие символы и их соответствие универсальным именам символов определяется реализацией.
(акцент мой)
И в соответствии с Руководством GCC по поведению, определяемому реализацией:
- Идентификатор персонажей.
Стандарты C и C++ позволяют идентификаторам состоять из
_
и буквенно-цифровые символы. C++ также допускает универсальные имена символов. C99 и более поздние стандарты C допускают как универсальные имена символов, так и символы, определяемые реализацией.GCC позволяет
$
'символ в идентификаторах как расширение для большинства целей. Это верно независимо отstd=
переключатель, так как это расширение не может конфликтовать с программами, соответствующими стандартам. Однако при предварительной обработке ассемблера доллары не являются символами-идентификаторами по умолчанию.
(акцент мой)
И снова в Tokenization, и упоминается в ответе Idav1s:
В качестве расширения GCC рассматривает
$
'как письмо. Это для совместимости с некоторыми системами, такими как VMS, где$
'обычно используется в системных именах функций и объектов. '$
'не является буквой в строго соответствующем режиме, или если вы указываете-$
вариант.
Потому что VMS использовал много системных функций и объектов, которые были названы$
, GCC разрешено $
быть включенным как характерный для реализации символ для совместимости в некоторых системах.
Специальные символы, такие как $
а также @
явно не разрешено спецификацией C быть в идентификаторе, но определенные символы (такие как $
здесь) может быть разрешено реализацией. GCC, например, позволяет $
в идентификаторах для большинства целей. То же самое касается Clang (так как большая часть его поведения, определяемого реализацией, совпадает с GCC), и MSVC.
В качестве расширения GCC рассматривает '$' как букву. Это для совместимости с некоторыми системами, такими как VMS, где "$" обычно используется в системных именах функций и объектов. '$' не является буквой в строго соответствующем режиме или если вы указали опцию -$. Смотрите Invocation.
Я изменил ваш var$
немного сниппет (чтобы исключить предупреждения, нас не волнует) и добавил сюда строго соответствующие флаги:
$ gcc -Wall -std=gnu99 -ansi -pedantic -Werror -O2 -o a.out source_file.c
Error(s):
source_file.c: In function ‘main’:
source_file.c:4:13: error: '$' in identifier or number [-Werror]
int var$ = 3;
^
cc1: all warnings being treated as errors
Так что если gcc
даны правильные флаги, $
тоже не скомпилируется.
Ну, собственно говоря, var$
тоже недействительно.
Некоторые компиляторы позволяют вам использовать $
как символ в идентификаторах, наряду с a
-z
, A
-Z
, 0
-9
, а также _
, Это нестандартное расширение. Это полезно, потому что компиляторы для некоторых других языков (я думаю, включая FORTRAN) позволяют $
в идентификаторах, и вы можете пытаться написать код C, который взаимодействует с этими другими языками. Очевидно, gcc - один из компиляторов, который разрешает это расширение.
Разрешение на продление @
было бы гораздо более необычным. Возможно, я когда-то видел странный компилятор, который позволял бы вам его использовать, но, поскольку я не знаю, как он используется, и требует меньше, думаю, никто его не предлагает.