Действительно ли маркер порядка байтов является действительным идентификатором? - PullRequest
11 голосов
/ 22 ноября 2011

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

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

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

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

Я что-то упустил, или это не проблема?

Ответы [ 3 ]

4 голосов
/ 23 ноября 2011

Сначала я хочу сказать, что описываемая вами проблема вряд ли имеет значение.Если вашему компилятору требуется спецификация UTF-8 для обработки файла с использованием кодировки UTF-8, то у вас не может быть файла, в котором отсутствует спецификация UTF-8, но где источник начинается с U + FEFF в кодировке UTF-8,Если вашему компилятору не требуется спецификация UTF-8 для обработки файлов UTF-8, вам не следует помещать спецификации UTF-8 в свои исходные файлы (по словам Майкла Каплана, «ОСТАНОВИТЬ ИСПОЛЬЗОВАНИЕ WINDOWS NOTEPAD»)).

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

Теперь к моему ответу.

Поиск физических символов исходного файла не определен стандартом C ++.Объявление кодировки исходного файла компилятору, форматов файлов для хранения физических исходных символов и сопоставления физических символов исходного файла с базовой исходной кодировкой - все это определяется реализацией.Поддержка обработки 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 спецификация не вызвана спецификацией C ++;и если вы абсолютно не вынуждены взаимодействовать с мертвыми программами, которым это необходимо (другими словами, программами, которые могут обрабатывать только подмножество строк Unicode, начинающихся с U + FEFF), не используйте спецификацию UTF-8.

4 голосов
/ 22 ноября 2011

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

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

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

0 голосов
/ 23 ноября 2011

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

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

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

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

...