Подтвердить что ты не робот

Что представляет собой "действительный" идентификатор C?

В предложении @Zaibis (и в связи с моим собственным ответом на Каковы допустимые символы для имен макросов?, а также 😃 (и другие символы Юникода) в идентификаторах, недопустимых g++))...

clang позволяет много "сумасшедших" персонажей. Хотя я изо всех сил пытался найти много рифмы или разума - о том, почему некоторые из них разрешены (🔴 ϟ ツ ⌘ ☁ ½), а другие нет (▶ ︎ ∀ ★ ©).

Например, следующее компилирует A-OK (clang-700.1.76)

#define 💩  ?:          // OK (Pile of poo)
#define  ■  @end        // OK (HALFWIDTH BLACK SQUARE)
#define 🅺  @interface  // OK (NEGATIVE SQUARED LATIN CAPITAL LETTER K)
#define P  @protocol   // OK (FULLWIDTH LATIN CAPITAL LETTER P)

все же все результаты приводят к той же ошибке компилятора...

Macro name must be an identifier.

#define  ☎   TEL
#define ❌    NO
#define  ⇧   UP
#define  〓  ==
#define  🍎   APPLE

clang Документы ссылаются на проблему, указав только...

... поддержка расширенных идентификаторов в C99 и С++. Эта функция позволяет идентификаторам содержать определенные символы Юникода, как указано стандартом активного языка; эти символы могут быть записаны непосредственно в исходном файле с использованием кодировки UTF-8 или упомянуты с использованием универсальных имен символов (\ u00E0,\U000000E0).

Итак, я думаю, я спрашиваю.. что такое "стандарт активного языка" и как я могу найти авторитетный источник для того, какие идентификаторы являются законными.

Я создал следующий код, чтобы увидеть, что с ним будет делать clang. Из примерно 63488 возможных идентификаторов проверено 23 предупреждения и 9506 сгенерированных ошибок. Это оставляет почти 54 000 действительных символов для использования в идентификаторах. Конечно, достаточно, но кто режет? И почему?

4b9b3361

Ответ 1

Как уже упоминалось, приложение D ISO/IEC 9899: 2011 шестнадцатеричные значения символов, действительные для универсальных имен символов в C11. (Я не буду повторять это здесь.) Я искал ответ на вопрос "почему" этот список был выбран.

Стандарты набора символов

Во-первых, существуют два соответствующих стандарта, определяющих набор символов: ISO/IEC 10646 (определение UCS) и Unicode. Чтобы еще больше смутить (или упростить) вещи, они оба определяют одни и те же символы, поскольку ISO и Unicode поддерживают их synchronized. UCS - это, по сути, только символ, сопоставляющий значения с набором символов ( "репертуар" ), в то время как Unicode также дает дополнительные определения, такие как сравнение строк в алфавитном порядке сортировки (сопоставление), которые указывают "канонически эквивалентные" символы (normalization) и двунаправленный алгоритм для обработки символов на языках, написанных справа налево, и многое другое.

Универсальные имена символов в C

Универсальные имена символов (UCN) - это функция, недавно добавленная в C99 (ISO/IEC 9899: 1999). В "Обосновании международного стандарта --- Языки программирования --- C" (Rev.2, октябрь 1999 г.), целью было "включить использование любого" родного "символа в идентификаторах, строковых литералах и символьных константах, сохраняя при этом цель переносимости of C" (п. 5.2.1). В этом разделе мы продолжаем рассказывать о том, как кодировать эти символы в формах C (формы \U и \U в сравнении с многобайтовыми символами или родными кодировками) и политическими моделями того, как с ним бороться (стр .14, см. PDF страница 22).

Обоснование

Я надеялся, что тот же "обоснование" документа с 1999 года послужит причиной того, почему каждый расширенный диапазон символов был выбран как приемлемый для C99 UCN. В целом обоснование Приложения I:

Приложение я Универсальные имена символов для идентификаторов (нормативные)

Новая функция C9X.

Это не очень логично. Они даже не знали, в каком году будет опубликован стандарт C, поэтому он просто называется "C9X". Позднее обоснованный документ с 2003 года немного более просвещает:

Приложение D Универсальные имена символов для идентификаторов (нормативные)

Новая функция для C99.

Цель состоит в том, чтобы поддерживать ток с ISO/IEC TR 10176.

ISO/IEC TR 10176 - "Рекомендации для подготовка стандартов языка программирования". Это в основном путеводитель для людей, которые пишут стандарты языка программирования. В нем содержатся рекомендации по использованию наборов символов в языках программирования, а также "рекомендуемый расширенный репертуар для пользовательских идентификаторов" (Приложение A). Но эта цитата из документа обоснования 2003 года - это всего лишь "намерение сохранить текущее", а не обязательство строго соблюдать TR 10176.

Существует общедоступная таблица ISO/IEC TR 10176: 2003. Значения символов относятся к ISO 10646. Таблица классифицирует диапазоны символов из множества языков как "прописные" Lu; "нижний регистр" Ll; "число, десятичная цифра" Nd, "пунктуация, коннектор" Pc; и т.д. Должно быть понятно, что использовать такие классификации для языка программирования.

Важным напоминанием является то, что TR 10176 является Техническим отчетом, а не стандартом. Я нашел несколько ссылок на него на форумах и в документах, относящихся к другим языкам программирования, таким как язык Ada, COBOL и D. Большая часть обсуждений заключалась в том, насколько тесно эти языки должны соответствовать требованиям стандарта TR 10176 (не являясь стандартом) и жалоб, что TR 10176 отстает от обновлений ISO 10646.

Возможно, наиболее просвещательным является документ WG21/N3146: "Рекомендации для расширенных символов идентификатора для C и С++". Он начинается с комментария в 2010 году к органу стандартов, рекомендующему ограничения на исходные символы идентификаторов. В нем упоминаются похожие жалобы на C, ссылающиеся на TR 10176, и излагаются предложения о том, какие символы должны быть разрешены в качестве начальных символов идентификатора на основе ограничений от Идентификатор Unicode и синтаксис шаблонов и Общие XML-синтаксические конструкции. WG21/N3146 дает предлагаемую формулировку, которая позже появилась в стандарте C11 ISO/IEC 9899: 2011. В конце документа есть таблица, которая помогает пролить свет на выбранные диапазоны символов.

Разрешенные и недопустимые символы в C11

Ниже представлен скомпилированный список диапазонов для расширенных символов идентификатора. Диапазоны жирный шрифт - это те, что указаны в C11 (ISO/IEC 9899: 2011 Приложение D). Некоторые комментарии добавляются в выделенные курсивом диапазоны, не указанные в C11 (т.е. Не разрешенные). Они либо помечены как WG21/N3146, как это запрещено Unicode UAX # 31 или Общие XML-синтаксические конструкции или запрещены каким-либо другим комментарием.

00A8, 00AA, 00AD, 00AF, 00B2-00B5, 00C0-00D6, 00D8-00F6, 00F8-00FF: (Различные символы, такие как женские и мужские º порядковые индикаторы, гласные с диакритические знаки, числовые символы, такие как надстрочные числа, дроби и т.д.)

(предыдущие пробелы): Все не разрешены UAX31 и/или XML. (Обычно знаки знаков препинания, такие как "", денежные символы ¥ £, математические операторы × ÷ и т.д.)

0100-167F: (латинский, греческий, кириллический, арабский, тайский, эфиопский и т.д. - многие другие)

1680: "Блок Ogham содержит script -специфическое пространство:"

1681-180D: (Ogham, Tagalog, Mongolian и т.д.)

180E: "Монгольский блок содержит script -специфическое пространство"

180F-1FFF: (Дополнительные языки... фонетика, расширенная латынь и греческая и т.д.)

2000: запускает блок "Общая пунктуация", но некоторые из них разрешены:

200B-200D, 202A-202E, 203F-2040, 2054, 2060-206F: (выбор из блока "Общая пунктуация" )

2070-218F: "Суперскрипты и подписи, символы валют, сочетание диакритических знаков для символов, буквенных символов, числовых форм"

2190-245F: "Стрелки, математические операторы, различные технические, управляющие изображения, оптическое распознавание символов"

2460-24FF: "Enclosed Alphanumerics"

2500: запускает "Чертеж коробки, элементы блока, геометрические фигуры" и т.д.

2776-2793: (некоторые дингбаты и круговые дингбаты)

2794-2BFF: (другой набор дингбатов, математические символы, стрелки, шаблоны Брайля и т.д.)

2C00-2DFF, 2E80-2FFF: "Glagolitic, Latin Extended-C, Coptic, Georgian Supplement, Tifinagh, Ethiopic Extended, Cyrillic Extended-A" (также радикальное дополнение CJK)

3000: (начало "Символы и пунктуация CJK", разрешены некоторые варианты)

3004-3007, 3021-302F, 3031-303F: (разрешены "Символы и знаки препинания CJK" )

3040-D7FF: "Хирагана, Катакана", больше идеограмм CJK, радикалов и т.д.

D800-F8FF: (Здесь начинается High и Low Surrogate Areas (числовое пространство, необходимое для кодирования), и Частное использование)

F900-FD3D, FD40-FDCF, FDF0-FE44, FE47-FFFD: выбор из "Идеограмм совместимости CJK", "Арабских презентационных форм" и т.д. 10000-1FFFD, 20000-2FFFD, 30000-3FFFD, 40000-4FFFD, 50000-5FFFD, 60000-6FFFD, 70000-7FFFD, 80000-8FFFD, 90000-9FFFD, A0000-AFFFD, B0000-BFFFD, C0000-CFFFD, D0000-DFFFD, E0000-EFFFD: WG21/N3146 дает обоснование для этих конечных диапазонов:

Дополнительная частная область использования простирается от F0000 до 10FFFF; оба [AltId] и [XML2008] запрещают символы в этом диапазоне.

Кроме того, [AltId] запрещает, как не-символы, последние два кодовые позиции каждой плоскости, т.е. каждая позиция формы P FFFE или P FFFF, для любого значения P.

"Диапазоны символов, которые не разрешены первоначально" из C11 Приложение D.2 0300-036F, 1DC0-1DFF, 20D0-20FF, FE20-FE2F.

С этим WG21/N3146, размещенные рядом с Приложение D стандарта стандарт C11, многое может быть выведено о том, как они выстраиваются в линию. Например, математические операторы и знаки препинания, по-видимому, не допускаются. Надеюсь, что это проливает свет на "почему" или "как" выбраны допустимые символы.


TL;DR; версия

  • Авторитетным источником для символов юридического идентификатора является стандарт C11 ISO/IEC 9899: 2011 (См. Приложение D).
  • Этот список основан на техническом отчете, ISO/IEC TR 10176, но с изменения.

Ответ 2

C 2011 стандарт

6.4.2 Идентификаторы

6.4.2.1 Общие сведения
...
3       Каждое универсальное имя символа в идентификаторе должно обозначать символ, кодировка которого в ISO/IEC 10646 входит в один из диапазонов, указанных в D.1. 71) Начальный символ не должно быть универсальным символьным именем, обозначающим символ, кодировка которого один из диапазонов, указанных в D.2. Реализация может допускать многобайтовые символы которые не являются частью базового набора символов источника, отображаемого в идентификаторах; какие символы и их соответствие универсальным именам символов определяется реализацией.
...
71). В системах, в которых линкеры не могут принимать расширенные символы, кодирование универсального символа имя может использоваться при формировании действительных внешних идентификаторов. Например, некоторые неиспользованные символ или последовательность символов могут использоваться для кодирования \u в универсальном имени символа. Расширенные символы могут содержать длинный внешний идентификатор.
...

Приложение D

(нормативное)

Универсальные имена символов для идентификаторов

1       Этот раздел перечисляет шестнадцатеричные значения кода, которые действительны в универсальных символьных именах в идентификаторах. D.1 Диапазоны допустимых символов

1     00A8, 00AA, 00AD, 00AF, 00B2-00B5, 00B7-00BA, 00BC-00BE, 00C0-00D6, 00D8-00F6, 00F8-00FF

2     0100-167F, 1681-180D, 180F-1FFF

3     200B-200D, 202A-202E, 203F-2040, 2054, 2060-206F

2 & middot;   5 & ​​nbsp;     3004-3007, 3021-302F, 3031-303F

6     3040-D7FF

7     F900-FD3D, FD40-FDCF, FDF0-FE44, FE47-FFFD

8     10000-1FFFD, 20000-2FFFD, 30000-3FFFD, 40000-4FFFD, 50000-5FFFD, 60000-6FFFD, 70000-7FFFD, 80000-8FFFD, 90000-9FFFD, A0000-AFFFD, B0000-BFFFD, C0000-CFFFD, D0000-DFFFD, E0000-EFFFD

D.2 Диапазоны символов, отклоненные первоначально

1     0300-036F, 1DC0-1DFF, 20D0-20FF, FE20-FE2F

Ответ 3

Синтаксис идентификаторов, которые включают имена макросов, представлен в разделе 6.4.2 стандарта C2011, как это интерпретируется в свете добавления D.1. В этих положениях указывается, что каждый идентификатор может содержать символы подчеркивания, латинские буквы верхнего и нижнего регистра, десятичные цифры, последовательности символов, составляющие "универсальные имена символов" (с ограничениями), и любой другой символ, определенный реализацией.

Универсальные имена символов (UCN) - это escape-последовательности Unicode, подобные тем, которые предоставляются Java, Python и некоторыми другими языками: они начинаются с обратного слэша (\), за которым следуют u или u, и четыре или восемь шестнадцатеричных цифр соответственно. Существуют некоторые ограничения на конкретные последовательности шестнадцатеричных цифр, которые могут быть использованы, некоторые общие, другие специфичные для контекста идентификатора. Обратите внимание, однако, что синтаксически единственным дополнительным символом, который позволяет предоставить UCN в идентификаторах, является обратная косая черта; все остальные символы, которые могут отображаться в UCN, также разрешены в идентификаторах вне контекста UCN.

Таким образом, говоря синтаксически и ограничивая обсуждение символами, которые стандарт должен допускать в идентификаторах, подчеркивания, (без акцента) латинские буквы, десятичные цифры и обратная косая черта являются единственными символами, которые требуют C, должны поддерживаться в идентификаторы. Поддержка обратной косой черты требуется только в контексте UCN, и не все допустимые UCN разрешены в идентификаторах. Кроме того, стандарт не требует поддержки цифр в качестве первых символов идентификаторов.

С другой стороны, стандарт довольно либеральный, позволяя "другим символам, определенным для реализации" в идентификаторах, в том числе в качестве первого символа. Даже десятичные цифры, которые в противном случае не могут быть первым символом в идентификаторе, в принципе могут быть разрешены на этой позиции в соответствии с этим положением по усмотрению реализации. Если вы хотите, чтобы ваш код был переносимым среди реализаций, вы избегаете полагаться на это положение в любом месте. Если вы хотите знать, какие символы допускает ваша конкретная реализация, вы должны проконсультироваться с его документацией.

Каждая стандартно-совместимая реализация должна документировать свое поведение в отношении каждой детали, объявленной стандартом для реализации. Например, документация GCC указывает, что знак доллара ($) разрешен в идентификаторах на большинстве целевых архитектур. Вы сами связаны и цитируете документацию Клэнга о той же детализированной детализации, которая является более либеральной - она ​​позволяет всем символам, которые могут быть представлены в идентификаторах через UCN, также быть представимыми по последовательностям байтов UTF-8. Во многих случаях, если вы показываете или печатаете исходный код, содержащий такие последовательности байтов, они будут отображаться как один отображаемый символ.

Ответ 4

Как уже упоминалось, C11 Standard определяет несколько допустимых диапазонов символов Юникода.

  • 00A8, 00AA, 00AD, 00AF, 00B2-00B5, 00B7-00BA, 00BC-00BE, 00C0-00D6, 00D8-00F6, 00F8-00FF
  • 0100-167F, 1681-180D, 180F-1FFF
  • 200B-200D, 202A-202E, 203F-2040, 2054, 2060-206F
  • 2070-218F, 2460-24FF, 2776-2793, 2C00-2DFF, 2E80-2FFF
  • 3004-3007, 3021-302F, 3031-303F
  • 3040-D7FF
  • F900-FD3D, FD40-FDCF, FDF0-FE44, FE47-FFFD
  • 10000-1FFFD, 20000-2FFFD, 30000-3FFFD, 40000-4FFFD, 50000-5FFFD, 60000-6FFFD, 70000-7FFFD, 80000-8FFFD, 90000-9FFFD, A0000-AFFFD, B0000-BFFFD, C0000-CFFFD, D0000-DFFFD, E0000-EFFFD

Это также означает наличие нескольких диапазонов символов, исключенных из использования.
Из ваших примеров:

  • ☎ есть 260E и из блока "Разное символы": 2600-26FF, что означает, что вы потеряли все эти
  • ❌ есть 274C и из блока "Dingbats": 2700-27BF, который все эти, но некоторые из них разрешены ( 2776−2793)
  • ⇧ есть 21E7 и из блока "Стрелки": 2190-21FF, что означает, что вы потеряли на все эти
  • 〓 есть 3013 и из блока CJK Symbols and Pctctuation: 3000-303F, который все эти, но некоторые из них допускается.
  • 🍎 есть 1F34E и из блока "Разное символы и пиктограммы": 1F300-1F5FF, который все эти и на самом деле должен работать < br/" > (возможно, проблема clang? btw, это не отображается на моем домашнем компьютере (Ubuntu), но на моем рабочем ПК (Win7))