float_control pragma

指定函数的浮点行为。

语法

#pragma float_control
#pragma float_control( precise, { on | off } [ , push ] )
#pragma float_control( except, { on | off } [ , push ] )
#pragma float_control( { push | pop } )

选项

preciseon | offpush
指定是启用 (on) 还是禁用 (off) 精确浮点语义。 有关与 /fp:precise 编译器选项差异的信息,请参阅“注解”部分。 可选 push 令牌将 float_control 的当前设置推送到内部编译器堆栈。

excepton | offpush
指定是启用 (on) 还是禁用 (off) 浮点异常语义。 可选 push 令牌将 float_control 的当前设置推送到内部编译器堆栈。

precise 也设置为 on 时,只能将 except 设置为 on

push
将当前的 float_control 设置推送到内部编译器堆栈。

pop
从内部编译器堆栈的顶部移除 float_control 设置,使其成为新的 float_control 设置。

注解

float_controlpragma 的行为与 /fp 编译器选项不同。 float_controlpragma 只管理部分浮点行为。 必须将其与 fp_contractfenv_accesspragma 指令组合在一起才能重新创建 /fp 编译器选项。 下表显示了每个编译器选项的等效 pragma 设置:

选项 float_control(precise, *) float_control(except, *) fp_contract(*) fenv_access(*)
/fp:strict on on off on
/fp:precise on off off* off
/fp:fast off off on off

* 在 Visual Studio 2022 之前的 Visual Studio 版本中,/fp:precise 行为默认为 fp_contract(on)

选项 float_control(precise, *) float_control(except, *) fp_contract(*) fenv_access(*)
/fp:strict on on off on
/fp:precise on off off off
/fp:fast off off on off

换句话说,可能需要结合使用多个 pragma 指令来模拟 /fp:fast/fp:precise/fp:strict 命令行选项。

组合使用 float_controlfenv_access 浮点 pragma 指令的方式有一些限制:

  • 仅当启用精确语义时,才能使用 float_controlexcept 设置为 on。 精确语义可以通过 float_controlpragma 或使用 /fp:precise/fp:strict 编译器选项来启用。

  • 启用异常语义(无论是通过 float_controlpragma 还是 /fp:except 编译器选项)时,不能使用 float_control 来关闭 precise

  • 除非通过 float_controlpragma 或编译器选项启用了精确语义,否则无法启用 fenv_access

  • 启用 fenv_access 时,不能使用 float_control 关闭 precise

这些限制意味着一些浮点 pragma 指令的顺序非常重要。 若要使用 pragma 指令从快速模式转到严格模式,请使用以下代码:

#pragma float_control(precise, on)  // enable precise semantics
#pragma fenv_access(on)             // enable environment sensitivity
#pragma float_control(except, on)   // enable exception semantics
#pragma float_control(precise, on)  // enable precise semantics
#pragma fenv_access(on)             // enable environment sensitivity
#pragma float_control(except, on)   // enable exception semantics
#pragma fp_contract(off)            // disable contractions

若要使用 float_controlpragma 从严格模式转到快速模式,请使用以下代码:

#pragma float_control(except, off)  // disable exception semantics
#pragma fenv_access(off)            // disable environment sensitivity
#pragma float_control(precise, off) // disable precise semantics
#pragma fp_contract(on)             // enable contractions

如果未指定任何选项,则 float_control 不起作用。

float_control 指令打开 preciseexcept 时,它将禁用收缩。 使用 float_control 关闭 preciseexcept 将还原先前的收缩设置。 可以使用 fp_contractpragma 指令更改收缩时的编译器行为。 float_control(push)float_control(pop) 将收缩设置作为 float_control 设置的一部分推送并弹出到内部编译器堆栈。 这是 Visual Studio 2022 中的新行为。 以前的编译器版本中的 float_control 指令不会影响收缩设置。

示例

以下示例演示如何通过使用 pragmafloat_control 捕获溢出浮点异常。

// pragma_directive_float_control.cpp
// compile with: /EHa
#include <stdio.h>
#include <float.h>

double func( ) {
   return 1.1e75;
}

#pragma float_control (except, on)

int main( ) {
   float u[1];
   unsigned int currentControl;
   errno_t err;

   err = _controlfp_s(&currentControl, ~_EM_OVERFLOW, _MCW_EM);
   if (err != 0)
      printf_s("_controlfp_s failed!\n");

   try  {
      u[0] = func();
      printf_s ("Fail");
      return(1);
   }

   catch (...)  {
      printf_s ("Pass");
      return(0);
   }
}
Pass

另请参阅

Pragma 指令以及 __pragma_Pragma 关键字
fenv_access pragma
fp_contract pragma