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

С++ 11 делает множество дополнений к списку кодовых точек Unicode, разрешенных в идентификаторах (§E). Это включает в себя знак порядка байтов, который включен в диапазон FE47-FFFD.

Консультирование браузера символов, этот диапазон включает в себя целую кучу случайных вещей, начиная с WHITE SESAME DOT и PRESENTATION FORM FOR VERTICAL LEFT SQUARE BRACKET, включая некоторую "маленькую пунктуацию", фантастическую арабскую, спецификацию здесь, полуширина и полноразмерные азиатские символы, и, наконец, включает в себя REPLACEMENT CHARACTER, который обычно используется для указания разбитого текстового рендеринга.

Конечно, это какая-то ошибка. Они почувствовали необходимость исключить "кунжутные точки", независимо от того, что есть, но знак байтового байта a.k.a. устаревшее безразличное пространство без ширины - это честная игра? Когда есть еще одно неразрывное пространство для словаря a.k.a., которое также было допустимым идентификатором в С++ 11?

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

Я что-то упускаю, или это беспроблемный дефект?

Ответ 1

Моя попытка интерпретации: в стандарте излагаются только правила абстрактного фрагмента исходного кода.

В вашем компиляторе есть понятие "набор символов источника", в котором говорится о том, как кодируется конкретный файл исходного кода. Если это кодирование является "UTF-16" (то есть без спецификатора BE/LE и, следовательно, требует спецификации), то спецификация не является частью потока с кодовой точкой, а только из огибающей файла.

Только после того, как файл был декодирован, поток codepoint передается самому компилятору.

Ответ 2

Сначала я хочу сказать, что проблема, которую вы описываете, вряд ли имеет значение. Если вашему компилятору требуется спецификация UTF-8 для обработки файла с использованием кодировки UTF-8, тогда у вас не может быть файла, который не имеет спецификации UTF-8, но где источник начинается с U + FEFF в кодировке UTF-8, Если ваш компилятор не требует спецификации UTF-8 для обработки файлов UTF-8, вам не следует помещать спецификации UTF-8 в исходные файлы (по словам Майкла Каплана, "STOP USING WINDOWS NOTEPAD" ).

Но да, если компилятор разбивает спецификации, вы можете получить поведение, отличное от предполагаемого. Если вы хотите (неразумно) начать исходный файл с U + FEFF, но (разумно) отказаться от размещения спецификаций в своем источнике, вы можете использовать универсальное имя символа:\uFEFF.

Теперь на мой ответ.

Извлечение физических символов исходного файла не определяется стандартом С++. Объявить кодировку исходного файла компилятору, форматы файлов для хранения физических исходных символов и сопоставление символов физического исходного файла с основной кодировкой источника - это вся реализация. Поддержка обработки U + FEFF в начале исходного файла в качестве подсказки кодирования лежит в этой области.

Если компилятор поддерживает дополнительную спецификацию UTF-8 и не может отличить файл, где дополнительная спецификация поставляется с той, где она есть, а исходный код начинается с U + FEFF, то это дефект в дизайне компилятора, и более широко в идее самой спецификации UTF-8.

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

Спецификация UTF-8 была выбрана в качестве подсказки для кодирования по нескольким причинам. Во-первых, он не влияет на видимый текст и поэтому может быть намеренно вставлен в текст без видимого эффекта. Во-вторых, файлы, отличные от UTF-8, вряд ли будут включать байты, которые будут ошибочно приняты за спецификацию UTF-8. Однако это не мешает использовать спецификацию как нечто иное, чем угадывание. Нет ничего, что говорит, что обычный текстовый файл ISO-8859-1 не может начинаться с U + 00EF U + 00BB U + 00BF, например. Эта последовательность символов, закодированных в ISO-8859-1, имеет ту же кодировку, что и U + FEFF, закодированная в UTF-8: 0xEF 0xBB 0xBF. Любое программное обеспечение, которое опирается на обнаружение спецификации UTF-8, будет смущено таким файлом ISO-8859-1. Таким образом, спецификация не может быть авторитетным источником, хотя предположение, основанное на ней, почти всегда будет работать.

Помимо того, что использование спецификации UTF-8 сводится к угадыванию, есть вторая причина, что это ужасная идея. Это ошибочное предположение, что изменения в тексте, которые не влияют на визуальное отображение этого текста, не имеют никакого эффекта. Это предположение может быть ошибочным, если текст используется для чего-то другого, кроме визуального отображения, например, когда он используется в тексте, предназначенном для чтения компьютером в качестве исходного кода.

Итак, в заключение: эта проблема с спецификацией UTF-8 не вызвана спецификацией С++; и если вам абсолютно не нужно взаимодействовать с запрограммированными мозгом программами (другими словами, программы, которые могут обрабатывать только подмножество строк Unicode, которые начинаются с U + FEFF), не используйте спецификацию UTF-8.

Ответ 3

Эта часть спецификации С++ (и ваш вопрос) связана с спецификацией unicode. Подумайте, что в любом нормальном файле unicode может появиться FFFE (или что-то еще) внутри файла, так как мы должны их интерпретировать?

В соответствии со стандартом Юникода спецификация char в начале потока/файла не рассматривается как символ и игнорируется в представлении.

Когда они говорят, что файлы С++ могут быть в формате Unicode, они также ограничивают всю спецификацию С++ спецификацией unicode. Здесь закон юникода также контролирует спецификацию С++.

Поскольку стандарт Юникода уже определил это поведение (пропуская спецификацию в начале), у писателей стандарта С++ была хорошая причина не включать это в свои документы. Любой, кто реализует компилятор Unicode С++, также учитывает стандарт unicode.