Compartilhar via


_control87, _controlfp, __control87_2

Obtém e define a palavra de controle de ponto flutuante. Uma versão mais segura de _controlfp está disponível; confira _controlfp_s.

Sintaxe

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
);

Parâmetros

new
Novos valores de bit da palavra de controle.

mask
Máscara para novos bits da palavra de controle a ser definida.

x86_cw
Preenchido com a palavra de controle da unidade de ponto flutuante x87. Passe 0 (NULL) para definir apenas a palavra de controle SSE2.

sse2_cw
Palavra de controle da unidade de ponto flutuante SSE. Passe 0 (NULL) para definir apenas a palavra de controle x87.

Valor retornado

Para _control87 e _controlfp, os bits no valor retornado indicam o estado do controle de ponto flutuante. Para obter uma definição completa dos bits retornados por _control87, consulte FLOAT.H.

Para __control87_2, o valor retornado é 1, o que indica êxito.

Comentários

A função _control87 obtém e define a palavra de controle de ponto flutuante. A palavra de controle de ponto flutuante permite que o programa altere os modos de precisão, arredondamento e infinito, dependendo da plataforma. Também é possível usar _control87 para mascarar ou remover a máscara das exceções de ponto flutuante. Se o valor de mask for igual a 0, _control87 obterá a palavra de controle de ponto flutuante. Se mask for diferente de zero, um novo valor para a palavra de controle será definido: para qualquer bit que esteja ativado (ou seja, igual a 1) em mask, o bit correspondente em new será usado para atualizar a palavra de controle. Em outras palavras, fpcntrl = ((fpcntrl & ~mask) | (new & mask)), em que fpcntrl é a palavra de controle de ponto flutuante.

Observação

Por padrão, as bibliotecas em tempo de execução mascaram todas as exceções de ponto flutuante.

_controlfp é uma versão portátil independente de plataforma de _control87 que é quase idêntica à função _control87. Se o código for direcionado a mais de uma plataforma, use _controlfp ou _controlfp_s. A diferença entre _control87 e _controlfp está em como eles tratam valores DENORMAL. Para plataformas x86, x64, ARM e ARM64, _control87 pode definir e limpar a máscara de exceção DENORMAL OPERAND. _controlfp não modifica a máscara de exceção DENORMAL OPERAND. Este exemplo demonstra a diferença:

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

Os possíveis valores para a constante de máscara (mask) e os novos valores de controle (new) estão mostrados na tabela Máscaras e valores de palavra de controle. Use as constantes portáteis listadas abaixo (_MCW_EM, _EM_INVALID e assim por diante) como argumentos para essas funções, em vez de fornecer os valores hexadecimais explicitamente.

Plataformas Intel derivadas do x86 dão suporte a valores de entrada e saída DENORMAL em hardware. O comportamento do x86 é preservar valores DENORMAL. As plataformas ARM e ARM64, bem como as plataformas x64 que têm o suporte a SSE2 permitem que operandos e resultados DENORMAL sejam liberados ou forçados para zero. As funções _controlfp e _control87 fornecem uma máscara para alterar esse comportamento. O exemplo a seguir demonstra o uso dessa máscara.

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

Nas plataformas ARM e ARM64, as funções _control87 e _controlfp se aplicam ao registro FPSCR. Apenas a palavra de controle SSE2 armazenada no registro MXCSR é afetada em plataformas x64. Em plataformas x86, _control87 e _controlfp afetarão as palavras de controle do x87 e do SSE2, caso estejam presentes.

A função __control87_2 permite que unidades de ponto flutuante x87 e SSE2 sejam controladas juntas ou separadamente. Para alterar as duas unidades, passe os endereços dos dois inteiros para x86_cw e sse2_cw. Se desejar alterar apenas uma unidade, passe um endereço para esse parâmetro, mas passe 0 (NULL) para o outro. Se 0 for passado para um desses parâmetros, a função não terá efeito sobre essa unidade de ponto flutuante. É útil quando parte do seu código usa a unidade de ponto flutuante x87 e outra parte do código usa a unidade de ponto flutuante SSE2.

Se você usar __control87_2 para definir valores diferentes para as palavras de controle de ponto flutuante, talvez _control87 ou _controlfp não poderá retornar uma única palavra de controle para representar o estado de ambas as unidades de ponto flutuante. Nesse caso, essas funções definem o sinalizador EM_AMBIGUOUS no valor inteiro retornado para indicar uma inconsistência entre as duas palavras de controle. O sinalizador EM_AMBIGUOUS é um aviso indicando que a palavra de controle retornada poderá não representar o estado de ambas as palavras de controle de ponto flutuante com precisão.

Nas plataformas ARM, ARM64 e x64, não há suporte para a alteração do modo de infinito nem da precisão de ponto flutuante. Se a máscara de controle de precisão for usada na plataforma x64, a função gerará uma declaração e o manipulador de parâmetro inválido será invocado, conforme descrito em Validação de parâmetro.

Observação

Não há suporte para __control87_2 nas plataformas ARM, ARM64 ou x64. Se você usar __control87_2 e compilar o programa para as plataformas ARM, ARM64 ou x64, o compilador gerará um erro.

Essas funções são ignoradas quando você usa /clr (Compilação do Common Language Runtime) para compilar. O CLR (Common Language Runtime) dá suporte apenas à precisão de ponto flutuante padrão.

Controlar máscaras de palavras e valores

Para a máscara _MCW_EM, limpar a máscara define a exceção, o que permite a exceção de hardware; configurar a máscara oculta a exceção. Se ocorrer um _EM_UNDERFLOW ou _EM_OVERFLOW, nenhuma exceção de hardware será gerada até que a próxima instrução de ponto flutuante seja executada. Para gerar uma exceção de hardware imediatamente após _EM_UNDERFLOW ou _EM_OVERFLOW, chame a instrução FWAIT do MASM.

Máscara Valor hexa Constante Valor hexa
_MCW_DN (Controle desnormalizado) 0x03000000 _DN_SAVE

_DN_FLUSH
0x00000000

0x01000000
_MCW_EM (Máscara de exceção de interrupção) 0x0008001F _EM_INVALID

_EM_DENORMAL

_EM_ZERODIVIDE

_EM_OVERFLOW

_EM_UNDERFLOW

_EM_INEXACT
0x00000010

0x00080000

0x00000008

0x00000004

0x00000002

0x00000001
_MCW_IC (Controle de infinito)

(Sem suporte em plataformas ARM ou x64).
0x00040000 _IC_AFFINE

_IC_PROJECTIVE
0x00040000

0x00000000
_MCW_RC (Controle de arredondamento) 0x00000300 _RC_CHOP

_RC_UP

_RC_DOWN

_RC_NEAR
0x00000300

0x00000200

0x00000100

0x00000000
_MCW_PC (Controle de precisão)

(Sem suporte em plataformas ARM ou x64).
0x00030000 _PC_24 (24 bits)

_PC_53 (53 bits)

_PC_64 (64 bits)
0x00020000

0x00010000

0x00000000

Requisitos

Rotina Cabeçalho necessário
_control87, _controlfp, _control87_2 <float.h>

Para obter informações sobre compatibilidade, consulte Compatibilidade.

Exemplo

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

Confira também

Suporte matemático e de ponto flutuante
_clear87, _clearfp
_status87, _statusfp, _statusfp2
_controlfp_s