Противоречие в стандарте C18 (относительно наборов символов)?
Читаем в стандарте C18:
5.1.1.2 Этапы перевода
Приоритет синтаксических правил перевода определяется следующими этапами.
- Многобайтовые символы физического исходного файла сопоставляются определенным реализацией способом с исходным набором символов (при необходимости вводятся символы новой строки для индикаторов конца строки).
Это означает, что набор символов исходного файла декодируется и отображается в исходный набор символов.
Но тогда вы можете прочитать:
5.2.1 Наборы символов
Должны быть определены два набора символов и связанные с ними последовательности упорядочения: набор, в который записываются исходные файлы (исходный набор символов), и набор, интерпретируемый в среде выполнения (набор символов выполнения).
Это означает, что набор символов исходного файла является исходным набором символов.
Возникает вопрос: какой из них я понял неправильно, а какой на самом деле?
РЕДАКТИРОВАТЬ: На самом деле я был неправ. Смотрите мой ответ ниже.
3 ответа
Это означает, что набор символов исходного файла декодируется и отображается в исходный набор символов.
Нет, это не значит. Я считаю, что исходный код уже записан в исходном наборе символов - какой именно имеет смысл "сопоставить исходный набор символов с исходным набором символов"? Либо они являются частью набора, либо нет. Если вы выберете неправильную кодировку для исходного кода, он будет просто отклонен до того, как начнется предварительная обработка.
На этапе перевода 1 выполняются две вещи, совершенно не связанные с этим:
Разрешает триграфы, которые представляют собой стандартизированные многобайтовые последовательности.
Сопоставьте многобайтовые символы с исходным набором символов (определенным в 5.2.1).
Исходный набор символов состоит из базового набора символов, который по сути представляет собой латинский алфавит плюс различные общие символы (5.2.1/3), и расширенного набора символов, зависящего от локали и реализации.
Определение многобайтовых символов находится в 5.2.1.2:
Исходный набор символов может содержать многобайтовые символы, используемые для представления элементов расширенного набора символов. Набор символов выполнения может также содержать многобайтовые символы, которые не обязательно должны иметь ту же кодировку, что и исходный набор символов.
Имеются в виду различные специфические для конкретного региона особые случаи, такие как триграфы, зависящие от локали.
Все это многобайтовое безумие восходит к первой стандартизации в 1990 году - согласно анекдотам тех, кто был частью этого комитета, это произошло потому, что члены из разных европейских стран не могли использовать различные символы на своих национальных клавиатурах.
(Я не уверен, насколько широко была распространена клавиша AltGr на таких клавиатурах в то время. В любом случае, она остается ключевым элементом, который в любом случае вызывает серьезное нажатие кнопок при написании C на неанглоязычных клавиатурах, чтобы получить доступ к{}[]
символы и т. д.)
Ну, в конце концов, кажется, я ошибался. Связавшись с Дэвидом Китоном из группы WG14 (они отвечают за стандарт C), я получил этот уточняющий ответ:
Есть тонкое различие. Исходный набор символов - это набор символов, в котором записываются исходные файлы. Однако исходный набор символов - это просто список доступных символов, который ничего не говорит о кодировке.
Фаза 1 отображает многобайтовую кодировку исходного набора символов на сами абстрактные исходные символы.
Другими словами, персонаж выглядит так:
<байт 1><байт 2>
отображается на это:
<персонаж 1>
Первая - это кодировка, представляющая символ в исходном наборе символов, в котором была написана программа. Второй - абстрактный символ в исходном наборе символов.
Вы столкнулись с кросс-компиляцией, когда программа компилируется на одной архитектуре и выполняется на другой архитектуре, и эти архитектуры имеют разные наборы символов.
5.1.1.2 активен на раннем этапе чтения, когда входной файл преобразуется в единый набор символов компилятора, который явно должен содержать все символы, требуемые программой C.
Однако при кросс-компиляции набор символов выполнения может быть другим. 5.2.1 допускает такую возможность. Когда компилятор генерирует код, он должен преобразовать все символьные и строковые константы в набор символов целевой платформы. На современных платформах это не работает, но на некоторых древних платформах это не так.