Share via


_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

_controlfp_s 之間的差異 _control87 在於如何處理反正規值。 針對 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 [Common Language Runtime 編譯] 進行編譯時,會忽略此函式,因為 Common Language Runtime (CLR) 僅支援預設浮點精確度。

根據預設,此函式的全域狀態會限定于應用程式。 若要變更此行為,請參閱 CRT 中的全域狀態。

遮罩常數和值

針對 _MCW_EM 遮罩,清除它會設定例外狀況,以允許硬體例外狀況;設定它則會隱藏例外狀況。 如果發生 _EM_UNDERFLOW_EM_OVERFLOW,則除非執行下一個浮點指令,否則不會擲回任何硬體例外狀況。 若要在 或 _EM_OVERFLOW 之後 _EM_UNDERFLOW 立即產生硬體例外狀況,請呼叫 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

另請參閱

數學和浮點支援
_clear87, _clearfp
_status87, _statusfp, _statusfp2
_control87, _controlfp, __control87_2