Почему 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 - один из компиляторов, который разрешает это расширение.

Разрешение на продление @ было бы гораздо более необычным. Возможно, я когда-то видел странный компилятор, который позволял бы вам его использовать, но, поскольку я не знаю, как он используется, и требует меньше, думаю, никто его не предлагает.

Другие вопросы по тегам