_controlfp_s
Возвращает и задает управляющее слово блока операций с плавающей запятой. Эта версия , __control87_2
_controlfp
имеет улучшения безопасности, как описано в функциях _control87
безопасности в 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
отлично от нуля, задается новое значение управляющего слова: для любого включенного бита (то есть равного 1) в параметре mask
соответствующий бит в параметре new
используется для обновления управляющего слова. Другими словами, fpcntrl = ((fpcntrl & ~mask) | (newControl & mask))
где fpcntrl
находится слово элемента управления с плавающей запятой. В этом сценарии currentControl
задано значение после завершения изменения. Это не старое битовое значение элемента управления.
Примечание.
По умолчанию библиотеки времени выполнения маскируют все исключения для операций с плавающей запятой .
_controlfp_s
почти идентичен _control87
функции на платформах Intel (x86), x64 и ARM. Если вы нацелены на платформы x86, x64 или ARM, можно использовать _control87
или _controlfp_s
.
Разница между _control87
и _controlfp_s
заключается в том, как они обрабатывают денормальные значения. Для платформ _control87
Intel (x86), x64 и ARM можно задать и очистить маску исключений DENORMAL OPERAND
. _controlfp_s
не изменяет маску DENORMAL OPERAND
исключения. В следующем примере показано это различие.
_control87( _EM_INVALID, _MCW_EM );
// DENORMAL is unmasked by this call.
unsigned int current_word = 0;
_controlfp_s( ¤t_word, _EM_INVALID, _MCW_EM );
// DENORMAL exception mask remains unchanged.
Возможные значения константы маски (mask
) и новые управляющие значения (newControl
) показаны в следующей таблице шестнадцатеричных значений. В аргументах этих функций вместо явных шестнадцатеричных значений следует использовать перечисленные ниже переносимые константы (_MCW_EM
, _EM_INVALID
и т. д.).
Платформы, производные от Intel (x86),поддерживают DENORMAL
входные и выходные значения в оборудовании. Поведение x86 заключается в сохранении DENORMAL
значений. Платформа ARM и платформы x64, поддерживающие SSE2, позволяют DENORMAL
операндам и результатам удаляться или принудительно нулю. Функции _controlfp_s
, _controlfp
и _control87
предоставляют маску для изменения такого поведения. В следующем примере показано использование этой маски:
unsigned int current_word = 0;
_controlfp_s(¤t_word, _DN_SAVE, _MCW_DN);
// Denormal values preserved on ARM platforms and on x64 processors with
// SSE2 support. NOP on x86 platforms.
_controlfp_s(¤t_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 затрагивается только слово элемента управления SSE2, хранящееся в регистре MXCSR. На платформах Intel (x86) функция _controlfp_s
влияет на управляющие слова как для x87, так и для SSE2 (при наличии). Два элемента управления могут быть несогласованы друг с другом (из-за предыдущего вызова__control87_2
, например); если между двумя словами элемента управления возникает несоответствие, _controlfp_s
задается EM_AMBIGUOUS
флаг.currentControl
Это предупреждение о том, что возвращаемое слово элемента управления может не представлять состояние обоих слов элемента управления с плавающей запятой точно.
В архитектурах ARM и x64 изменение режима бесконечности или точность с плавающей запятой не поддерживается. Если маска управления точностью используется на платформе x64, функция вызывает утверждение и вызывается обработчик недопустимых параметров, как описано в разделе "Проверка параметров".
Если маска не задана правильно, эта функция создает недопустимое исключение параметров, как описано в разделе проверки параметров. Если продолжение выполнения разрешено, эта функция возвращает EINVAL
и задает для errno
значение EINVAL
.
Эта функция игнорируется при использовании /clr
(компиляция среды CLR), так как среда CLR по умолчанию поддерживает только точность с плавающей запятой по умолчанию.
По умолчанию глобальное состояние этой функции ограничивается приложением. Чтобы изменить это поведение, см . статью "Глобальное состояние" в CRT.
Маскирование констант и значений
При очистке маски _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 |
Требования
Маршрут | Обязательный заголовок |
---|---|
_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