Dela via


_controlfp_s

Hämtar och anger flyttalskontrollens ord. Den här versionen av _control87, _controlfphar __control87_2 säkerhetsförbättringar enligt beskrivningen i Säkerhetsfunktioner i CRT.

Syntax

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

Parameterar

currentControl
Det aktuella bitvärdet control-word.

newControl
Nya bitvärden för kontroll-ord.

mask
Maskera för nya control-word-bitar som ska anges.

Returvärde

Noll om det lyckas eller en errno värdefelkod.

Anmärkningar

Funktionen _controlfp_s är en plattformsoberoende och säkrare version av _control87, som hämtar flyttalskontrollens ord till den adress som lagras i currentControl och anger den med hjälp newControlav . Bitarna i värdena anger flyttalskontrollens tillstånd. Med kontrolltillståndet för flyttal kan programmet ändra precisions-, avrundnings- och oändlighetslägena i det flyttalsbaserade matematikpaketet, beroende på plattformen. Du kan också använda _controlfp_s för att maskera eller avmaskera undantag från flyttalser.

Om värdet för mask är lika med 0 _controlfp_s hämtar du flyttalskontrollens ord och lagrar det hämtade värdet i currentControl.

Om mask är nonzero anges ett nytt värde för kontrollordet: För varje bit som har angetts (dvs. lika med 1) i maskanvänds motsvarande bit i new för att uppdatera kontrollordet. Med andra ord, fpcntrl = ((fpcntrl & ~mask) | (newControl & mask)) var fpcntrl är flyttalskontrollens ord. I det här scenariot currentControl anges värdet efter att ändringen har slutförts. Det är inte det gamla bitvärdet för kontroll-ord.

Anmärkning

Som standard maskerar körningsbiblioteken alla undantag från flyttal.

_controlfp_s är nästan identisk med _control87 funktionen på Intel-plattformarna (x86), x64 och ARM. Om du riktar in dig på x86-, x64- eller ARM-plattformar kan du använda _control87 eller _controlfp_s.

Skillnaden mellan _control87 och _controlfp_s är i hur de behandlar denormala värden. För Intel-plattformar _control87 (x86), x64 och ARM kan du ange och rensa undantagsmasken DENORMAL OPERAND . _controlfp_s ändrar inte undantagsmasken DENORMAL OPERAND . Det här exemplet visar skillnaden:

_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.

Möjliga värden för maskkonstanten (mask) och nya kontrollvärden (newControl) visas i följande hexadecimala värden. Använd de portabla konstanterna som anges nedan (_MCW_EM, _EM_INVALIDoch så vidare) som argument för dessa funktioner i stället för att uttryckligen ange hexadecimala värden.

Intel-härledda plattformar (x86) stöder DENORMAL indata- och utdatavärdena i maskinvaran. X86-beteendet är att bevara DENORMAL värden. ARM-plattformen och de x64-plattformar som har stöd för SSE2 gör att DENORMAL operander och resultat kan tömmas eller tvingas till noll. Funktionerna _controlfp_s, _controlfpoch _control87 ger en mask för att ändra det här beteendet. I följande exempel visas hur masken används:

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.

Den här funktionen ignoreras när du använder /clr (Common Language Runtime Compil) för att kompilera eftersom CLR (Common Language Runtime) endast stöder standardprecision för flyttals.

På x64 påverkas endast SSE2-kontrollordet som lagras i MXCSR-registret. Det går inte att ändra oändlighetsläget eller flyttalsprecisionen. Om precisionskontrollmasken används på x64-plattformen genererar funktionen ett påstående och den ogiltiga parameterhanteraren anropas enligt beskrivningen i Parameterverifiering.

På x86 _controlfp_s påverkar kontrollorden för både x87 och SSE2, om det finns. Det är möjligt att de två kontrollorden är inkonsekventa med varandra (på grund av ett tidigare anrop till , till __control87_2exempel); om det finns en inkonsekvens mellan de två kontrollorden _controlfp_sEM_AMBIGUOUS anger du flaggan i currentControl. Det är en varning om att det returnerade kontrollordet kanske inte representerar tillståndet för båda flyttalskontrollorden korrekt.

Om masken inte är korrekt inställd genererar den här funktionen ett ogiltigt parameterfel, enligt beskrivningen i Parameterverifiering. Om körningen tillåts fortsätta returneras EINVAL och anges errno den här funktionen till EINVAL.

Som standard är den här funktionens globala tillstånd begränsat till programmet. Information om hur du ändrar det här beteendet finns i Globalt tillstånd i CRT.

Armplattformar

  • Det går inte att ändra oändlighetsläget eller flyttalsprecisionen. Om precisionskontrollmasken används på x64-plattformen genererar funktionen ett påstående och den ogiltiga parameterhanteraren anropas enligt beskrivningen i Parameterverifiering.
  • På ARM32 (upphört) stöder Windows inte FP-undantag.
  • På ARM64 ändrar du FPCR-registret korrekt genom att avmaskera hela _MCW_EM eller några bitar från det (_EM_INEXACT, , _EM_UNDERFLOW_EM_OVERFLOW_EM_ZERODIVIDE, och )._EM_INVALID Undantag från flyttal som genereras av standardmatematikfunktioner, till exempel Ogiltig åtgärd från std::acos, är undantagna från det här beteendet och kan ignoreras eller höjas korrekt beroende på FPCR-registret. Mer information finns i Översikt över ARM32 ABI-konventioner.
  • På ARM64EC fångar Windows undantag från processorns flyttal och inaktiverar dem i FPCR-registret. Detta säkerställer konsekvent beteende för olika processorvarianter.

Maskera konstanter och värden

För masken _MCW_EM anger rensningen undantaget, vilket tillåter maskinvarufelet. Om du anger det döljs undantaget. Om en _EM_UNDERFLOW eller _EM_OVERFLOW inträffar utlöses inget maskinvaruundantag förrän nästa flyttalsinstruktion körs. Om du vill generera ett maskinvarufel direkt efter _EM_UNDERFLOW eller _EM_OVERFLOWanropar du instruktionen FWAIT MASM .

Ansiktsmask Hexvärde Konstant Hexvärde
_MCW_DN (Denormal kontroll) 0x03000000 _DN_SAVE

_DN_FLUSH
0x00000000

0x01000000
_MCW_EM (Avbryt undantagsmask) 0x0008001F _EM_INVALID

_EM_DENORMAL

_EM_ZERODIVIDE

_EM_OVERFLOW

_EM_UNDERFLOW

_EM_INEXACT
0x00000010

0x00080000

0x00000008

0x00000004

0x00000002

0x00000001
_MCW_IC (Oändlig kontroll)

(Stöds inte på ARM- eller x64-plattformar.)
0x00040000 _IC_AFFINE

_IC_PROJECTIVE
0x00040000

0x00000000
_MCW_RC (Avrundningskontroll) 0x00000300 _RC_CHOP

_RC_UP

_RC_DOWN

_RC_NEAR
0x00000300

0x00000200

0x00000100

0x00000000
_MCW_PC (Precisionskontroll)

(Stöds inte på ARM- eller x64-plattformar.)
0x00030000 _PC_24 (24 bitar)

_PC_53 (53 bitar)

_PC_64 (64 bitar)
0x00020000

0x00010000

0x00000000

Kravspecifikation

Rutin Obligatoriskt huvud
_controlfp_s <float.h>

Mer kompatibilitetsinformation finns i Kompatibilitet.

Exempel

// 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

Se även

Stöd för matematik och flyttals
_clear87, _clearfp
_status87, , _statusfp_statusfp2
_control87, , _controlfp__control87_2