_controlfp_s

获取并设置浮点控制字。 此版本的 _control87_controlfp__control87_2 具有 CRT 中的安全功能中所述的安全增强功能。

语法

errno_t _controlfp_s(
    unsigned int *currentControl,
    unsigned int newControl,
    unsigned int mask
);

参数

currentControl
当前控制字位值。

newControl
新的控制字位值。

mask
要设置的新控制字位掩码。

返回值

如果成功,则为零;否则为 errno 值错误代码。

备注

_controlfp_s 函数是 _control87 的一个与平台无关的、更安全的版本,它将浮点控制字置入存储于 currentControl 中的地址,并使用 newControl 对其进行设置。 值中的位表示浮点控制状态。 浮点控制状态允许程序在浮点数学包中更改精度、舍入和无穷模式,具体取决于平台。 还可使用 _controlfp_s 屏蔽或取消屏蔽浮点异常。

如果 mask 的值等于 0,则 _controlfp_s 获取浮点控制字,并存储 currentControl 中检索到的值。

如果 mask 为非零的值,则为控制字设置新值:对于 mask 中设置的任何位(即等于 1),new 中的对应位被用于更新控制字。 即 fpcntrl = ((fpcntrl & ~mask) | (newControl & mask)),其中 fpcntrl 是浮点控制字。 在此方案中,currentControl 在更改完成后被设置为该值;它并非旧的控制字位值。

注意

默认情况下,运行时库屏蔽所有浮点异常。

_controlfp_s 几乎等同于 Intel (x86)、x64 以及 ARM 平台上的 _control87 函数。 如果你正面向 x86、x64 或 ARM 平台,则可以使用 _control87_controlfp_s

_control87_controlfp_s 之间的差异在于它们看待 denormal 值的方式。 对于 Intel (x86)、x64、和 ARM 平台,_control87 可以设置和清除 DENORMAL OPERAND 异常掩码。 _controlfp_s 不修改 DENORMAL OPERAND 异常掩码。 此示例演示了差别:

_control87( _EM_INVALID, _MCW_EM );
// DENORMAL is unmasked by this call.
unsigned int current_word = 0;
_controlfp_s( &current_word, _EM_INVALID, _MCW_EM );
// DENORMAL exception mask remains unchanged.

下列十六进制值表中显示了掩码常量的可能值 (mask) 和新的控制值 (newControl)。 请使用下面列出的可移植常量 (_MCW_EM_EM_INVALID,等等)作为这些函数的参数,而不是显式提供十六进制值。

Intel (x86) 派生的平台支持硬盘中的 DENORMAL 输入和输出值。 x86 行为是为了保留 DENORMAL 值。 具有 SSE2 支持的 ARM 平台和 x64 平台允许刷新 DENORMAL 操作数和结果,或强制为零。 _controlfp_s_controlfp_control87 函数提供更改此行为的掩码。 下面的示例演示此掩码的使用:

unsigned int current_word = 0;
_controlfp_s(&current_word, _DN_SAVE, _MCW_DN);
// Denormal values preserved on ARM platforms and on x64 processors with
// SSE2 support. NOP on x86 platforms.
_controlfp_s(&current_word, _DN_FLUSH, _MCW_DN);
// Denormal values flushed to zero by hardware on ARM platforms
// and x64 processors with SSE2 support. Ignored on other x86 platforms.

在 ARM 平台上,将 _controlfp_s 函数应用于 FPSCR 寄存器。 在 x64 体系结构中,仅存储在 MXCSR 寄存器中的 SSE2 控制字受到影响。 在 Intel (x86) 平台上,_controlfp_s 会对 x87 和 SSE2 的控制字(如果存在)产生影响。 两个控制字有可能彼此不一致(例如,因为之前调用了 __control87_2);如果在两个控制字之间存在不一致性,则 _controlfp_s 将在 currentControl 中设置 EM_AMBIGUOUS 标志。 这是一条警告,指示所返回的控制字可能没有准确地表示两个浮点控制字的状态。

在 ARM 和 x64 体系结构中,不支持更改无穷模式或浮点精度。 如果在 x64 平台上使用精度控制掩码,则函数引发断言并调用无效的参数处理程序,如参数验证中所述。

如果未正确设置掩码,则此函数生成无效的参数异常,如参数验证中所述。 如果允许执行继续,则此函数将返回 EINVAL 并将 errno 设置为 EINVAL

使用 /clr(公共语言运行时编译) 进行编译时,将忽略此函数,因为公共语言运行时 (CLR) 仅支持默认的浮点精度。

默认情况下,此函数的全局状态范围限定为应用程序。 若要更改此行为,请参阅 CRT 中的全局状态

掩码常量和值

对于 _MCW_EM 掩码,清除掩码将设置异常,这会允许硬件异常;设置它可隐藏异常。 如果出现 _EM_UNDERFLOW_EM_OVERFLOW,则在执行下一步浮点指令之前,不会引发任何硬盘异常。 若要在 _EM_UNDERFLOW_EM_OVERFLOW 后立即生成硬件异常,请调用 FWAIT MASM 指令。

Mask 十六进制值 常数 十六进制值
_MCW_DN (非常规控制) 0x03000000 _DN_SAVE

_DN_FLUSH
0x00000000

0x01000000
_MCW_EM(中断异常掩码) 0x0008001F _EM_INVALID

_EM_DENORMAL

_EM_ZERODIVIDE

_EM_OVERFLOW

_EM_UNDERFLOW

_EM_INEXACT
0x00000010

0x00080000

0x00000008

0x00000004

0x00000002

0x00000001
_MCW_IC(无穷控制)

(在 ARM 或 x64 平台上不受支持。)
0x00040000 _IC_AFFINE

_IC_PROJECTIVE
0x00040000

0x00000000
_MCW_RC舍入控制) 0x00000300 _RC_CHOP

_RC_UP

_RC_DOWN

_RC_NEAR
0x00000300

0x00000200

0x00000100

0x00000000
_MCW_PC(精度控制)

(在 ARM 或 x64 平台上不受支持。)
0x00030000 _PC_24(24 位)

_PC_53(53 位)

_PC_64(64 位)
0x00020000

0x00010000

0x00000000

要求

例程 必需的标头
_controlfp_s <float.h>

有关兼容性的详细信息,请参阅 兼容性

示例

// crt_contrlfp_s.c
// processor: x86
// This program uses _controlfp_s to output the FP control
// word, set the precision to 24 bits, and reset the status to
// the default.

#include <stdio.h>
#include <float.h>
#pragma fenv_access (on)

int main( void )
{
    double a = 0.1;
    unsigned int control_word;
    int err;

    // Show original FP control word and do calculation.
    err = _controlfp_s(&control_word, 0, 0);
    if ( err ) /* handle error here */;

    printf( "Original: 0x%.4x\n", control_word );
    printf( "%1.1f * %1.1f = %.15e\n", a, a, a * a );

    // Set precision to 24 bits and recalculate.
    err = _controlfp_s(&control_word, _PC_24, MCW_PC);
    if ( err ) /* handle error here */;

    printf( "24-bit:   0x%.4x\n", control_word );
    printf( "%1.1f * %1.1f = %.15e\n", a, a, a * a );

    // Restore default precision-control bits and recalculate.
    err = _controlfp_s(&control_word, _CW_DEFAULT, MCW_PC);
    if ( err ) /* handle error here */;

    printf( "Default:  0x%.4x\n", control_word );
    printf( "%1.1f * %1.1f = %.15e\n", a, a, a * a );
}
Original: 0x9001f
0.1 * 0.1 = 1.000000000000000e-002
24-bit:   0xa001f
0.1 * 0.1 = 9.999999776482582e-003
Default:  0x9001f
0.1 * 0.1 = 1.000000000000000e-002

另请参阅

数学和浮点支持
_clear87_clearfp
_status87_statusfp_statusfp2
_control87_controlfp__control87_2