如果 pragma STDC FENV_ACCESS 不存在,是否意味着默认舍入模式?

2024-04-15

我对 C 标准的解释有疑问,最新草案取自http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2454.pdf http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2454.pdf.

标准评价

该标准定义了pragma STD FENV_ACCESS并指出(7.6.1p2):

The FENV_ACCESS pragma provides a means to inform the implementation when a program might
access the floating-point environment to test floating-point status flags or run under non-default
floating-point control modes.

目前尚不清楚为什么该编译指示需要在非默认浮点控制模式下运行。是不是因为

  • 设置这些非默认模式需要写入控制模式寄存器,或者
  • 即使已经设置了非默认当前模式,编译指示始终是必需的?

在标准的这一段后面,我们发现:

If part of a program tests floating-point status flags or establishes non-default floating-point
mode settings using any means other than the FENV_ROUND pragmas, but was translated with the
state for the FENV_ACCESS pragma "off", the behavior is undefined.

看起来测试当前模式而不改变它不是未定义的行为。但同一段的脚注指出:

In general, if the state of FENV_ACCESS is "off", the translator can assume that the flags are
not tested, and that default modes are in effect, except where specified otherwise by an
FENV_ROUND pragma.

问题

因此,如果未指定 pragma FENV_ACCESS,是否意味着默认舍入模式有效?

假设 pragma FENV_ROUND 也不存在,并且编译器假定 FENV_ACCESS 默认情况下处于关闭状态,这是向后兼容所必需的。

Example

考虑以下源代码:

#include <math.h>
float func_01(float x) {
    return nearbyint(x);
}

功能nearbyint被描述为(7.12.9.3)使用当前舍入模式进行舍入。但代码中没有pragma FENV_ACCESS。这是否意味着当前的舍入模式可以被忽略并且nearbyintroundeven?


C 草案 n2454

我根据当前的 C 标准 2018 写了这个答案,但问题询问的是即将推出的标准草案。经审查,草案存在重大变化,本答复不适用。

值得注意的是,草案 n2454 在 7.6.1 2 中指出:

…如果程序的一部分测试浮点状态标志或使用除FENV_ROUNDpragmas,但与状态一起翻译为FENV_ACCESSpragma“off”,行为未定义......

值得注意的是,其中缺少 C 2018 中的这段文本,该文本出现在“非默认浮点模式设置”之后:

…或在非默认模式设置下运行,…

C 2018 文本意味着如果代码编译为FENV_ACCESSon 设置非默认模式并设置编译的代码FENV_ACCESSoff,则行为未定义,仅仅因为代码编译为FENV_ACCESSoff 正在非默认模式下运行。草稿文本不包含此内容,这似乎暗示调用者可以更改模式并调用使用 编译的代码FENV_ACCESS关闭,并且应该定义行为。这意味着代码编译为FENV_ACCESSoff 必须准备好在任何浮点模式下运行。

草案中的同一段落还包含以下新案文:

(当执行从用翻译的程序的一部分传递时FENV_ACCESS“关闭”翻译为的部分FENV_ACCESS“on”时,浮点状态标志的状态未指定,浮点控制模式具有默认设置。)

考虑当例程 A 与FENV_ACCESS调用例程 B 时FENV_ACCESS离开。当 B 返回时,控制从程序的访问关闭部分传递到程序的访问打开部分。上面的句子表示浮点控制模式处于默认设置。换句话说,从访问关闭例程返回必须将浮点模式更改为默认值。这看起来很奇怪。所以我不准备更新这个答案来很好地涵盖草案。

2018年C题答案

目前尚不清楚为什么该编译指示需要在非默认浮点控制模式下运行。

这是因为,如果不知道浮点运算是否处于默认模式,则编译器生成的代码可能会有所不同(取决于 C 实现)。例如,当使用以下命令编译代码时FENV_ACCESS set to off,编译器可以编译对sin作为对假定默认舍入的快速版本的调用。但如果FENV_ACCESS被设定为on,它会将调用编译为较慢的版本,该版本测试舍入模式并使用正弦函数的相应实现。

因为必须生成的代码不同on and off版本,编译器必须知道是否FENV_ACCESS is on or off.

因此,如果未指定 pragma FENV_ACCESS,是否意味着默认舍入模式有效?

不可以。如果FENV_ACCESSpragma 不存在,编译器处于默认状态,这可能是on or off,这是实现定义的。

如果默认是off并且没有 pragma,那么,是的,默认的舍入模式should有效,这意味着,如果您正确设计了程序,则任何编译的代码都不会FENV_ACCESSpragma 永远不会在非默认舍入模式下执行。这由程序设计者来确保。

功能nearbyint被描述为(7.12.9.3)使用当前舍入模式进行舍入。但代码中没有pragma FENV_ACCESS。这是否意味着当前的舍入模式可以被忽略并且nearbyintroundeven?

如果代码与FENV_ACCESS set to off(默认或显式)调用nearbyint,那么编译器可以假设默认舍入模式有效,并且它可以调用快速版本nearbyint它本身采用默认的舍入模式。

请注意,round-to-nearest-ties-to-even 压倒了默认舍入模式,但除非附录 F 生效,否则 C 标准并未指定这一点。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如果 pragma STDC FENV_ACCESS 不存在,是否意味着默认舍入模式? 的相关文章

  • 部署 MVC4 项目时出错:找不到文件或程序集

    过去 我只需使用 Visual Studio 2012 发布到 AWS 菜单项即可部署我的 MVC4 网站 到 AWS Elastic Beanstalk 现在 程序可以在本地编译并运行 但无法部署 从消息来看 它似乎正在寻找不在当前部署的
  • C++ 求二维数组每一行的最大值

    我已经设法用这个找到我的二维数组的每一行的最小值 void findLowest int A Cm int n int m int min A 0 0 for int i 0 i lt n i for int j 0 j lt m j if
  • 如何在C++中实现模板类协变?

    是否可以以这样一种方式实现类模板 如果模板参数相关 一个对象可以转换为另一个对象 这是一个展示这个想法的例子 当然它不会编译 struct Base struct Derived Base template
  • Cygwin 下使用 CMake 编译库

    我一直在尝试使用 CMake 来编译 TinyXML 作为一种迷你项目 尝试学习 CMake 作为补充 我试图将其编译成动态库并自行安装 以便它可以工作 到目前为止 我已经设法编译和安装它 但它编译成 dll 和 dll a 让它工作的唯一
  • 使用 Microsoft Graph API 订阅 Outlook 推送通知时出现 400 错误请求错误

    我正在尝试使用 Microsoft Graph API 创建订阅以通过推送通知获取 Outlook 电子邮件 mentions 我在用本文档 https learn microsoft com en us graph api subscri
  • 如何在我的应用程序中使用 Windows Key

    Like Windows Key E Opens a new Explorer Window And Windows Key R Displays the Run command 如何在应用程序的 KeyDown 事件中使用 Windows
  • 为什么禁止在 constexpr 函数中使用 goto?

    C 14 对你能做什么和不能做什么有规则constexpr功能 其中一些 没有asm 没有静态变量 看起来相当合理 但标准也不允许goto in constexpr功能 即使它允许其他控制流机制 这种区别背后的原因是什么 我以为我们已经过去
  • 跨多个控件共享事件处理程序

    在我用 C 编写的 Windows 窗体应用程序中 我有一堆按钮 当用户的鼠标悬停在按钮上时 我希望按钮的边框发生变化 目前我有以下多个实例 每个按钮一个副本 private void btnStopServer MouseEnter ob
  • 将字符串从非托管代码传递到托管

    我在将字符串从非托管代码传递到托管代码时遇到问题 在我的非托管类中 非托管类 cpp 我有一个来自托管代码的函数指针 TESTCALLBACK FUNCTION testCbFunc TESTCALLBACK FUNCTION 接受一个字符
  • .Net Core / 控制台应用程序 / 配置 / XML

    我第一次尝试使用新的 ConfigurationBuilder 和选项模式进入 Net Core 库 这里有很多很好的例子 https docs asp net en latest fundamentals configuration ht
  • A* 之间的差异 pA = 新 A;和 A* pA = 新 A();

    在 C 中 以下两个动态对象创建之间的确切区别是什么 A pA new A A pA new A 我做了一些测试 但似乎在这两种情况下 都调用了默认构造函数 并且仅调用了它 我正在寻找性能方面的任何差异 Thanks If A是 POD 类
  • 使用安全函数在 C 中将字符串添加到字符串

    我想将文件名复制到字符串并附加 cpt 但我无法使用安全函数 strcat s 来做到这一点 错误 字符串不是空终止的 我确实设置了 0 如何使用安全函数修复此问题 size strlen locatie size nieuw char m
  • 像“1$”这样的位置参数如何与 printf() 一起使用?

    By man I find printf d width num and printf 2 1 d width num 是等价的 但在我看来 第二种风格应该与以下相同 printf d num width 然而通过测试似乎man是对的 为什
  • C 中的位移位

    如果与有符号整数对应的位模式右移 则 1 vacant bit will be filled by the sign bit 2 vacant bit will be filled by 0 3 The outcome is impleme
  • 什么是 C 语言的高效工作流程? - Makefile + bash脚本

    我正在开发我的第一个项目 该项目将跨越多个 C 文件 对于我的前几个练习程序 我只是在中编写了我的代码main c并使用编译gcc main c o main 当我学习时 这对我有用 现在 我正在独自开展一个更大的项目 我想继续自己进行编译
  • 在 URL 中发送之前对特殊字符进行百分比编码

    我需要传递特殊字符 如 等 Facebook Twitter 和此类社交网站的 URL 为此 我将这些字符替换为 URL 转义码 return valToEncode Replace 21 Replace 23 Replace 24 Rep
  • 已过时 - OpenCV 的错误模式

    我正在使用 OpenCV 1 进行一些图像处理 并且对 cvSetErrMode 函数 它是 CxCore 的一部分 感到困惑 OpenCV 具有三种错误模式 叶 调用错误处理程序后 程序终止 Parent 程序没有终止 但错误处理程序被调
  • 如何在 C# 中播放在线资源中的 .mp3 文件?

    我的问题与此非常相似question https stackoverflow com questions 7556672 mp3 play from stream on c sharp 我有音乐网址 网址如http site com aud
  • 更改显示的 DPI 缩放大小使 Qt 应用程序的字体大小渲染得更大

    我使用 Qt 创建了一些 GUI 应用程序 我的 GUI 应用程序包含按钮和单选按钮等控件 当我运行应用程序时 按钮内的按钮和字体看起来正常 当我将显示器的 DPI 缩放大小从 100 更改为 150 或 200 时 无论分辨率如何 控件的
  • 如何连接字符串和常量字符?

    我需要将 hello world 放入c中 我怎样才能做到这一点 string a hello const char b world const char C string a hello const char b world a b co

随机推荐