C Черновик n2454
Я написал этот ответ, основываясь на текущем стандарте C, 2018, но вопрос касается черновика для готовящегося стандарта. После просмотра черновика произошли существенные изменения, и этот ответ не применим.
Примечательно, что черновой вариант n2454 в 7.6.1: 2:
… Если часть программы тестируется Состояния с плавающей запятой отмечают или устанавливают нестандартные настройки режима с плавающей запятой, используя любые средства, кроме прагм FENV_ROUND
, но были переведены с состоянием для прагмы FENV_ACCESS
«выкл», поведение не определено…
Примечательно, что здесь отсутствует текст из C 2018, который появился сразу после «нестандартных настроек режима с плавающей запятой»:
… или работает в режиме не по умолчанию settings,…
Текст C 2018 означает, что если код, скомпилированный с FENV_ACCESS
, устанавливает режим не по умолчанию и отключает код, скомпилированный с FENV_ACCESS
, то поведение не определено только потому, что код, скомпилированный с FENV_ACCESS
off, работает в режиме не по умолчанию. Черновой текст не содержит этого, что, по-видимому, означает, что вызывающий абонент может изменить режим и код вызова, скомпилированный с выключенным FENV_ACCESS
, и поведение должно быть определено. Это означает, что код, скомпилированный с FENV_ACCESS
off, должен быть подготовлен к запуску в любом режиме с плавающей запятой.
Этот же абзац в черновике также содержит новый текст:
(Когда выполнение переходит из части программы, переведенной с FENV_ACCESS
«выкл.», в часть, переведенную с FENV_ACCESS
«вкл», состояние флагов состояния с плавающей запятой не определено, а режимы управления с плавающей запятой имеют настройки по умолчанию .)
Рассмотрим, что происходит, когда подпрограмма A с FENV_ACCESS
вызывает подпрограмму B с FENV_ACCESS
выключенной. Когда B возвращается, управление переходит от части доступа к программе к части программы доступа. В приведенном выше предложении говорится, что режимы управления с плавающей точкой находятся в своих настройках по умолчанию. Другими словами, возвращение из процедуры отключения доступа должно изменить режим с плавающей запятой на режим по умолчанию. Это кажется странным. Поэтому я не готов обновлять этот ответ, чтобы охватить черновик проекта.
Ответ за C 2018
Не ясно, почему эта прагма необходима для работы под стандартные режимы управления с плавающей точкой.
Это может быть связано с тем, что (в зависимости от реализации C) код, сгенерированный компилятором, должен быть другим, если неизвестно, что операции с плавающей точкой в режиме по умолчанию. Например, при компиляции кода с FENV_ACCESS
, установленным на off
, компилятор может скомпилировать вызов на sin
как вызов быстрой версии, которая предполагает округление по умолчанию. Но если для FENV_ACCESS
установлено значение on
, он скомпилирует вызов более медленной версии, которая тестирует режим округления и использует соответствующую реализацию функции синуса.
Поскольку код, который должен быть сгенерирован, отличается для on
и off
версий, компилятор должен знать, является ли FENV_ACCESS
on
или off
.
Так что, если не была указана прагма FENV_ACCESS, означает ли это значение по умолчанию действует режим округления?
Нет. Если прагма FENV_ACCESS
отсутствует, компилятор находится в состоянии по умолчанию, которое может быть on
или off
, и это определяется реализацией.
Если значение по умолчанию off
и прагмы нет, тогда да, режим округления по умолчанию должен быть активным, а это означает, что если вы правильно спроектировали свою программу, то любой код, скомпилированный без прагмы FENV_ACCESS
, никогда не выполняется в режим округления не по умолчанию. Это зависит от разработчика (ей) программы.
Функция nearbyint
описана (7.12.9.3) как выполнение округления с использованием текущего режима округления. Но код не имеет pragma FENV_ACCESS
. Означает ли это, что текущий режим округления может игнорироваться и nearbyint
совпадает с roundeven
?
Если код с FENV_ACCESS
, установленным на off
(по умолчанию или явно), вызывает nearbyint
, тогда компилятор может предположить, что действует режим округления по умолчанию, и он может вызвать быструю версию nearbyint
это само по себе предполагает режим округления по умолчанию.
Обратите внимание, что округление до ближайших связей с чётными значениями превосходит режим округления по умолчанию, но это не определяется стандартом C, если только Приложение F не эффект.