Share via


_control87, _controlfp, __control87_2

取得和設定浮點控制字組。 有更安全的 版本 _controlfp 可用;請參閱 _controlfp_s

語法

unsigned int _control87(
   unsigned int new,
   unsigned int mask
);
unsigned int _controlfp(
   unsigned int new,
   unsigned int mask
);
int __control87_2(
   unsigned int new,
   unsigned int mask,
   unsigned int* x86_cw,
   unsigned int* sse2_cw
);

參數

new
新的控制字組位元值。

mask
要設定之新控制字組位元的遮罩。

x86_cw
填入 x87 浮點單位的控制字組。 傳入 0 (NULL),僅設定 SSE2 控制字組。

sse2_cw
SSE 浮點單位的控制字組。 傳入 0 (NULL),僅設定 x87 控制字組。

傳回值

針對 _control87_controlfp,傳回值中的位元表示浮點控制狀態。 如需 所 _control87 傳回之位的完整定義,請參閱 FLOAT.H

針對 __control87_2,傳回值是 1,表示成功。

備註

_control87 函式會取得和設定浮點控制字組。 浮點控制字可讓程式根據平臺變更精確度、四捨五入和無限模式。 您也可以使用 _control87 來遮罩或取消遮罩浮點例外狀況。 如果 mask 的值等於 0,_control87 會取得浮點控制字組。 如果 mask 為非零,則會設定控制字組的新值:針對 mask 中為開啟的任何位元 (即等於 1),會使用 new 中的對應位元來更新控制字組。 換句話說, fpcntrl = ((fpcntrl & ~mask) | (new & mask)) 其中 fpcntrl 是浮點控制字。

注意

根據預設,執行階段程式庫會遮罩所有浮點例外狀況。

_controlfp 是與平臺無關的可攜式版本 _control87 ,幾乎與 函 _control87 式完全相同。 如果您的程式碼以多個平臺為目標,請使用 _controlfp_controlfp_s_control87_controlfp 之間的差異在於它們如何處理 DENORMAL 值。 針對 x86、x64、ARM 和 ARM64 平臺, _control87 可以設定及清除 DENORMAL OPERAND 例外狀況遮罩。 _controlfp 不會修改例外狀況 DENORMAL OPERAND 遮罩。 這個範例示範差異:

_control87( _EM_INVALID, _MCW_EM );
// DENORMAL is unmasked by this call
_controlfp( _EM_INVALID, _MCW_EM );
// DENORMAL exception mask remains unchanged

遮罩常數 () 和新控制項值 ( mask ) 的可能值會顯示在 [控制文字遮罩] 和 [ new 值] 資料表中。 使用下面所列的可攜式常數 (_MCW_EM_EM_INVALID 等) 作為這些函式的引數,而不是明確地提供十六進位值。

Intel x86 衍生的平臺支援 DENORMAL 硬體中的輸入和輸出值。 x86 行為是保留 DENORMAL 值。 具有 SSE2 支援的 ARM 和 ARM64 平臺和 x64 平臺可讓 DENORMAL 運算元和結果排清,或強制為零。 _controlfp_control87 函式提供遮罩來變更此行為。 下列範例示範如何使用此遮罩。

_controlfp(_DN_SAVE, _MCW_DN);
// Denormal values preserved on ARM platforms and on x64 processors with
// SSE2 support. NOP on x86 platforms.
_controlfp(_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 和 ARM64 平臺上, _control87_controlfp 函式會套用至 FPSCR 暫存器。 只有儲存在 MXCSR 暫存器中的 SSE2 控制字會在 x64 平臺上受到影響。 在 x86 平臺上, _control87 如果存在,則 _controlfp 會影響 x87 和 SSE2 的控制字組。

__control87_2 函式會一併或分開控制 x87 和 SSE2 浮點單位。 若要影響這兩個單位,請將兩個整數的 x86_cw 位址傳入 和 sse2_cw 。 如果您只想要影響一個單位,請傳入該參數的位址,但針對另一個單位傳入 0 ( NULL ) 。 如果針對其中一個參數傳遞 0,則此函式不會影響該浮點單位。 當程式碼的一部分使用 x87 浮點單位,而另一個部分使用 SSE2 浮點單位時,會很有用。

如果您使用 __control87_2 來設定浮點控制字的不同值,則 _control87_controlfp 可能無法傳回單一控制字來表示這兩個浮點單位的狀態。 在這種情況下,這些函式會在 EM_AMBIGUOUS 傳回的整數值中設定旗標,以表示這兩個控制字組之間的不一致。 旗 EM_AMBIGUOUS 標是傳回的控制字組可能無法正確表示這兩個浮點控制項字的狀態的警告。

在 ARM、ARM64 和 x64 平臺上,不支援變更無限模式或浮點精確度。 如果在 x64 平臺上使用有效位數控制遮罩,函式會引發判斷提示,並叫用不正確參數處理常式,如參數驗證 中所述

注意

__control87_2 ARM、ARM64 或 x64 平臺不支援。 如果您使用 __control87_2 和編譯 ARM、ARM64 或 x64 平臺的程式,編譯器會產生錯誤。

當您使用 /clr [Common Language Runtime 編譯] 進行編譯時,會忽略這些函式。 Common Language Runtime (CLR) 僅支援預設浮點精確度。

控制文字遮罩和值

針對 _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

需求

常式 必要的標頭
_control87, _controlfp, _control87_2 <float.h>

如需相容性詳細資訊,請參閱相容性

範例

// crt_cntrl87.c
// processor: x86
// compile by using: cl /W4 /arch:IA32 crt_cntrl87.c
// This program uses __control87_2 to output the x87 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_x87 = 0;
    int result;

    // Show original x87 control word and do calculation.
    result = __control87_2(0, 0, &control_word_x87, 0 );
    printf( "Original: 0x%.8x\n", control_word_x87 );
    printf( "%1.1f * %1.1f = %.15e\n", a, a, a * a );

    // Set precision to 24 bits and recalculate.
    result = __control87_2(_PC_24, MCW_PC, &control_word_x87, 0 );
    printf( "24-bit:   0x%.8x\n", control_word_x87 );
    printf( "%1.1f * %1.1f = %.15e\n", a, a, a * a );

    // Restore default precision-control bits and recalculate.
    result = __control87_2( _CW_DEFAULT, MCW_PC, &control_word_x87, 0 );
    printf( "Default:  0x%.8x\n", control_word_x87 );
    printf( "%1.1f * %1.1f = %.15e\n", a, a, a * a );
}
Original: 0x0009001f
0.1 * 0.1 = 1.000000000000000e-02
24-bit:   0x000a001f
0.1 * 0.1 = 9.999999776482582e-03
Default:  0x0009001f
0.1 * 0.1 = 1.000000000000000e-02

另請參閱

數學和浮點支援
_clear87, _clearfp
_status87, _statusfp, _statusfp2
_controlfp_s