неопределенный символ C/C++ как оператор

Я заметил, что символ/символ '`' и '@' не используется в качестве оператора в C/C++,

  1. Кто-нибудь знает причину или исторически, почему это так?
  2. если он действительно не используется, безопасно ли определять эти символы как другой оператор/оператор с помощью #define?

person uray    schedule 06.03.2010    source источник
comment
Обратите внимание, что @ широко используется в Objective-C (надмножество C).   -  person kennytm    schedule 06.03.2010
comment
я прошу строго на C или C++, а не на другой производной или надстройке, но все равно спасибо   -  person uray    schedule 06.03.2010


Ответы (3)


Обычно #define принимает только действительные идентификаторы в имени макроса, поэтому вы не можете:

#define @      at
#define @(x)   [x]

Аналогично с обратной цитатой. И вы не упомянули '$', который иногда допускается в идентификаторах.

Может быть расширение для компилятора, разрешающее такие сопоставления, но я бы не стал его использовать.


Что касается исторической причины этого, то существуют части набора символов ISO 646, которые зарезервированы для национальных реализаций национальных символов. Эти зарезервированные части включают символы, вызывающие проблемы, а функции триграфов и орграфов в стандарте C (и, следовательно, в стандарте C++) были добавлены в ISO C в 1989 и 1994 годах соответственно, чтобы обеспечить обходные пути для проблем.

Триграфы

Триграфы были добавлены в процессе стандартизации C89, чтобы людям, например, не приходилось видеть алфавитные символы (в скандинавских языках), используемые в их коде C (адаптировано из примера в B Stroustrup, «Design and Evolution of C++», с использованием Датский терминал):

#include <stdio.h>
int main(int argc, char **argvÆÅ)
æ
    if (argc < 1 øø *argvÆ1Å == 'Ø0') return 0;
    printf("Hello, %sØn", argvÆ1Å);
å

Или в кодовом наборе ISO 8859-1 (или любом из кодовых наборов ISO 8859-x):

#include <stdio.h>
int main(int argc, char **argv[])
{
     if (argc < 1 || argv[1] == '\0') return 0;
     printf("Hello, %s\n", argv[1]);
}

Триграфы были введены для создания нейтрального формата кода:

??=include <stdio.h>
int main(int argc, char **argv??(??))
??<
    if (argc < 1 ??!??! *argv??(1??) == '??/0') return 0;
    printf("Hello, %s??/n", argv??(1??));
??>

Это тоже не очень читаемо, но одинаково для всех.

Trigraph      Equivalent to
??/           \      backslash
??<           {      open brace
??>           }      close brace
??(           [      open square bracket
??)           ]      close square bracket
??=           #      hash (pound in American, but a pound is £ in English)
??'           ^      caret
??!           |      pipe
??-           ~      tilde

В стандарте сказано, что «других триграфов нет». Вот почему управляющая последовательность '\?' распознается (как простой знак вопроса - хотя предположительно это '??/?'). Обратите внимание, что коллекция компиляторов GNU (GCC) не интерпретирует триграфы, если вы не держите руку на пульсе (укажите '-trigraphs' в командной строке).

Диграфы

Орграфы были добавлены в 1994 году и не так распространены или навязчивы, как триграфы; они появляются только вне строк и строковых литералов. Орграфы:

Digraph       Equivalent to
<:            [
:>            ]
<%            {
%>            }
%:            #
%:%:          ##

Пример с использованием орграфов (и триграфов):

%:include <stdio.h>
%:include <iso646.h>
int main(int argc, char **argv<::>)
<%
    if (argc < 1 or *argv<:1:> == '??/0') return 0;
    printf("Hello, %s??/n", argv<:1:>);
%>

На знаке и обратной кавычке конкретно?

Если вы посмотрите на приведенный выше URL-адрес Википедии, вы увидите, что и «@», и «`» иногда заменяются национальными символами — и, следовательно, не являются хорошими идентификаторами. Дополнительная причина не использовать «@» заключается в том, что во время введения C «#» был символом стирания по умолчанию, а «@» был символом уничтожения (стирания строки) для терминалов. Таким образом, вы должны были помнить, чтобы избежать их , Так как '#' появлялся только в начале строки, это не было большой проблемой (использование '#' и '##' появилось намного позже - снова стандартизация), но '@' стер бы весь предыдущий ввод в строку. И это за несколько дней до «vi» — «ed — стандартный редактор Unix».

person Jonathan Leffler    schedule 06.03.2010
comment
Хороший улов на $ - например, он разрешен в идентификаторах GCC на большинстве платформ. - person Stephen Canon; 06.03.2010

Вероятно, это безопасно, но это почти определенно очень плохая идея. Поскольку @ не является стандартным оператором, любому другому, читающему ваш код, придется найти определение @, где бы вы его ни использовали. Мы называем функции, а не просто используем символы, чтобы люди, читающие код, могли понять, что он делает.

Кстати, Objective-C использует @. Не уверен, что это имеет отношение к вашему проекту, но если кто-то попытается использовать ваш код C из ObjC, весь его код сломается из-за вашего #define.

person Asher Dunn    schedule 06.03.2010
comment
Другими словами, я мог бы предотвратить связывание моих кодов с помощью Objective-C, используя символ @, верно?... - person uray; 06.03.2010
comment
@uray: Нет. Пользователи ObjC могут просто использовать самодельный заголовочный файл. - person kennytm; 06.03.2010
comment
Конечно, вы можете предотвратить использование ваших кодов в Objective-C, но они также не будут действительными для C. Каждая допустимая программа на C является допустимой программой на Objective-C. - person Stephen Canon; 06.03.2010

Что касается С:

Макрос #defined имеет имя, которое является идентификатором C (§6.10).

Идентификатор может состоять из _a-zA-Z0-9 (§6.4.2.1). Все остальное определяется реализацией. Если вы используете @ в имени макроса, это может работать на некоторых компиляторах (хотя я был бы удивлен), но не будет переносимым.

Я не знаю, как обстоят дела с C++.

person Stephen Canon    schedule 06.03.2010
comment
По сути, в этом контексте C и C++ одинаковы в том, что касается стандартных идентификаторов. - person Jonathan Leffler; 06.03.2010