Поделиться через


_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( &current_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(&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.

На платформах 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