_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