获取并设置浮点控制字。 此版本的 _control87
CRT _controlfp
__control87_2
具有安全增强功能。
语法
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( ¤t_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(¤t_word, _DN_SAVE, _MCW_DN);
// Denormal values preserved on ARM platforms and on x64 processors with
// SSE2 support. NOP on x86 platforms.
_controlfp_s(¤t_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.
使用 /clr
(公共语言运行时编译) 编译时,将忽略此函数,因为公共语言运行时 (CLR) 仅支持默认浮点精度。
在 x64 上,仅影响存储在 MXCSR 寄存器中的 SSE2 控制字。 不支持更改无穷大模式或浮点精度。 如果在 x64 平台上使用精度控制掩码,该函数将引发断言,并调用无效的参数处理程序,如 参数验证中所述。
在 x86 上,如果存在, _controlfp_s
则影响 x87 和 SSE2 的控制词。 两个控制字有可能彼此不一致(例如,因为之前调用了 __control87_2
);如果在两个控制字之间存在不一致性,则 _controlfp_s
将在 EM_AMBIGUOUS
中设置 currentControl
标志。 这是一条警告,指示所返回的控制字可能没有准确地表示两个浮点控制字的状态。
如果未正确设置掩码,此函数将生成无效的参数异常,如 参数验证中所述。 如果允许执行继续,则此函数将返回 EINVAL
并将 errno
设置为 EINVAL
。
默认情况下,此函数的全局状态范围限定为应用程序。 若要更改此行为,请参阅 CRT 中的全局状态。
Arm 平台
- 不支持更改无穷大模式或浮点精度。 如果在 x64 平台上使用精度控制掩码,该函数将引发断言并调用无效的参数处理程序,如 参数验证中所述。
- 在 ARM32(已停用)上,Windows 不支持 FP 异常。
- 在 ARM64 上,从它
_EM_INEXACT
(、、_EM_UNDERFLOW
_EM_OVERFLOW
、_EM_ZERODIVIDE
和_EM_INVALID
)中解掩整个_MCW_EM
或任何位,正确更改 FPCR 寄存器。 标准数学函数(如无效作)std::acos
引发的浮点异常不受此行为的影响,可以根据 FPCR 寄存器正确忽略或引发。 有关详细信息,请参阅 ARM32 ABI 约定概述。 - 在ARM64EC,Windows 捕获处理器浮点异常,并在 FPCR 寄存器中禁用它们。 这可确保不同处理器变体的行为一致。
掩码常量和值
对于 _MCW_EM
掩码,清除掩码将设置异常,这会允许硬件异常;设置它可隐藏异常。 如果出现 _EM_UNDERFLOW
或 _EM_OVERFLOW
,则在执行下一步浮点指令之前,不会引发任何硬盘异常。 若要在 _EM_UNDERFLOW
或 _EM_OVERFLOW
后立即生成硬件异常,请调用 FWAIT MASM
指令。
面具 | 十六进制值 | 常数 | 十六进制值 |
---|---|---|---|
_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
另请参阅
数学和浮点支持
%>
.- .
.- .