Что означает [Примечание] в абзаце поведения undefined в стандарте С++?

Как пользователь Tony указывает на, там [Примечание] в пункте 1.3.12 стандарта С++, говорящего

допустимый диапазон undefined варьируется от полного игнорирования ситуации с непредсказуемыми результатами, ведения во время перевода или выполнения программы документированным образом, характерным для среды...

Разве это не противоречит определению UB, в котором говорится, что ... этот международный стандарт не налагает никаких требований? Я имею в виду, что они говорят "нет требований", а затем говорят "допустимый UB" - прямо в том же абзаце.

Как следует понимать эту заметку? Действительно ли это ограничивает UB?

Ответ 1

Из § 6.5.1 из Часть 3 Директив ISO/IEC:

Примечания и примеры, интегрированные в текст стандарта должен использоваться только за предоставление дополнительной информации предназначенные для содействия пониманию или использования стандарта, и не должны содержат положения, необходимо соблюдать, чтобы в состоянии требовать соблюдения стандарт.

Таким образом, он полностью ненормативный (необязательный) и предназначен только для возможного разъяснения.

Ответ 2

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

Ответ 3

В этой заметке объясняется, что может сделать реализация, если она встречает код, для которого нет определенного поведения. Слово "допустимое" не предназначено для ограничения, а приведены некоторые примеры общего поведения.

Интересно отметить, что компилятор почти всегда должен что-то скомпилировать! Рассмотрим этот фрагмент кода:

void f() { 1 / 0; }

поведение переводчика при столкновении с этим не совсем определено, но он не может просто делать все, что ему нравится! Фактически, если это компилятор, по-прежнему требуется скомпилировать этот блок компиляции. Это связано с тем, что поведение программы, содержащей эту функцию, может быть хорошо определено! Компилятор не может знать, вызвана ли функция. На самом деле этот вопрос возник, когда функция была "main()", и контроль, несомненно, прошел через нулевое деление, а результат заключается в том, что компилятору не разрешено отклонять даже эту программу. Причина в том, что программа все еще хорошо сформирована, и соответствующий компилятор должен принимать все хорошо сформированные программы (и отклонять все неправильно сформированные и выдавать диагностическое сообщение об ошибке, если не указано иное).

Это нелегко сделать плохо сформированным, потому что трудно точно определить, как интеллектуальные компиляторы могут быть обнаружены при делении на ноль.

Так интересно, требование Стандарта о том, что оно "не налагает никаких требований", на самом деле очень близко к ошибочному. Это характеристики системы компиляции, поддерживающей отдельную компиляцию, которая не может определить, действительно ли выполняется кусок кода, для которого нет четко определенного поведения, и, следовательно, компилятор действительно требуется для компилировать что-то во всяком случае, потому что он не может вывести, если программа имеет поведение undefined.