Я пытаюсь понять универсальные имена символов в стандарте C11 и обнаружил, что черновик N1570 стандарта C11 содержит гораздо меньше деталей, чем стандарт C ++ 11, в отношении этапов перевода 1 и 5 и формирования и обработки UCN в пределах их. Это то, что каждый должен сказать:
N1570 Проект C11 5.1.1.2p1.1:
Физический исходный файл многобайтовая символы отображаются способом, определяемым реализацией, в исходный набор символов (ввод символов новой строки для индикаторов конца строки), если необходимо. Триграфные последовательности заменяются соответствующими односимвольными внутренними представлениями.
C ++ 11 2.2p1.1:
Символы физического исходного файла отображаются, в соответствии с реализацией, в основной исходный набор символов (ввод символов новой строки для индикаторов конца строки) при необходимости. Допустимый набор физических символов исходного файла определяется реализацией. Триграфные последовательности (2.4) заменяются соответствующими односимвольными внутренними представлениями. Любой символ исходного файла, не входящий в базовый набор символов (2.3), заменяется универсальным именем символа, которое обозначает этот символ. (Реализация может использовать любую внутреннюю кодировку, если фактический расширенный символ встречается в исходном файле, и тот же расширенный символ, выраженный в исходном файле, что и имя универсального символа (т. Е. С использованием нотации \ uXXXX), обрабатывается аналогично, за исключением случаев, когда эта замена возвращается в виде необработанного строкового литерала.)
N1570 Проект C11 5.1.1.2p1.5:
Каждый элемент исходного набора символов и escape-последовательность в символьных константах и строковых литералах преобразуются в соответствующий элемент набора символов выполнения; […]
C ++ 2.2p1.5:
Каждый элемент исходного набора символов в символьном литерале или строковом литерале, а также каждая escape-последовательность и универсальное-символьное имя в символьном литерале или неочищенном строковом литерале, преобразуется в соответствующий член набора символов выполнения; […]
(акцент был добавлен на различия)
В стандарте C ++ 11 совершенно ясно, что символы исходного файла, не входящие в базовый исходный набор символов, преобразуются в UCN, и что они обрабатываются точно так же, как и UCN в том же месте, за единственным исключением: Сыра-строка. То же самое относится и к С11? Когда компилятор C11 видит многобайтовый символ UTF-8, такой как °
переводит ли это слишком \u00b0
в фазе 1, и относиться к нему так же, как если бы \u00b0
появился там вместо этого?
Иными словами, в конце какой фазы перевода, если таковые имеются, следующие фрагменты кода преобразуются в текстуально эквивалентный формы впервые в С11?
const char* hell° = "hell°";
а также
const char* hell\u00b0 = "hell\u00b0";
Если в 2. ответ «нет», то на каком этапе перевода эти два идентификатора сначала понимаются как относящиеся к одной и той же вещи, несмотря на то, что они различаются по тексту?
Комментарии превратились в ответ
Интересный вопрос!
Стандарт C может оставить больше преобразований неустановленными, поскольку они определяются реализацией (а C не имеет необработанных строк, чтобы запутать проблему).
Могут ли процессы, предусмотренные C ++ 11 на этапах 1 и 5, быть признаны соответствующими требованиям в формулировке C11 (за исключением необработанных строк)?
Я думаю, что они фактически одинаковы; Разница возникает в основном из-за проблем с литералом, характерных для C ++. Как правило, стандарты C и C ++ стараются не делать вещи совершенно разными, и, в частности, стараются, чтобы работа препроцессора и низкоуровневый символ разбирались одинаково в обоих (что стало проще, так как C99 добавил поддержку C ++ //
комментарии, но которые, очевидно, стали сложнее с добавлением необработанных литералов в C ++ 11).
Однажды мне придется более тщательно изучить необработанные буквенные обозначения и их значение.
Во-первых, обратите внимание, что эти различия существуют с 1998 года; UCN были впервые представлены в C ++ 98, новом стандарте (ISO / IEC 14882, 1-е издание: 1998), а затем вошли в пересмотр C99 стандарта C; но комитет C (и существующие исполнители, и их ранее существовавшие реализации) не чувствовали, что путь C ++ был единственным способом добиться цели, особенно в угловых случаях и использовании меньших наборов символов, чем Unicode, или просто других; например, требование отправить таблицы сопоставления из независимо от поддерживаемых кодировок- Unicode был предметом озабоченности для поставщиков C в 1998 году.
Что касается других ответов, я не буду ничего добавлять к Джонатану.
Что касается вашего дополнительного вопроса о более детерминированном процессе C ++, который должен быть совместим со стандартом C, то, очевидно, цель — быть таковым; и если вы обнаружите угловой случай, который показывает иное (препроцессор, совместимый с C ++ 11, который не соответствует стандартам C99 и C11), то вам следует рассмотреть вопрос о том, чтобы спросить комитет WG14 о возможном дефекте.
Очевидно, что обратное неверно: можно написать препроцессор с обработкой UCN, который соответствует C99 / C11, но не стандартам C ++; самая очевидная разница с
#define str(t) #t
#define str_is(x, y) const char * x = y " is " str(y)
str_is(hell°, "hell°");
str_is(hell\u00B0, "hell\u00B0");
который C-совместимый препроцессор может отображать так же, как ваши примеры (и большинство так), и, как таковой, будет иметь отличные отображения; но у меня сложилось впечатление, что C ++ — совместимый препроцессор требуется для преобразования в (строго эквивалентный)
const char* hell° = "hell°" " is " "\"hell\\u00b0\"";
const char* hell\u00b0 = "hell\\u00b0" " is " "\"hell\\u00b0\"";
И последнее, но не менее важное: я считаю, что не так много компиляторов полностью соответствуют этому уровню детализации!