_fpreset

Description

Resets the floating-point package.

#include <float.h>

void _fpreset( void );

Remarks

The _fpreset function reinitializes the floating-point-math package. This function is usually used in conjunction with signal, system, or the _exec or _spawn functions.

If a program traps floating-point error signals (SIGFPE) with signal, it can safely recover from floating-point errors by invoking _fpreset and using longjmp.

In DOS versions prior to 3.0, a child process executed by _exec, _spawn, or system may affect the floating-point state of the parent process if an 8087, 80287, or 80387 coprocessor is used. If you are using either coprocessor, the following precautions are recommended:

The _exec, _spawn, and system functions should not be called during the evaluation of a floating-point expression.

The _fpreset function should be called after these routines if there is a possibility of the child process performing any floating-point operations.

Return Value

None.

Compatibility

Standards:None

16-Bit:DOS, QWIN, WIN, WIN DLL

32-Bit:DOS32X

See Also

_exec functions, signal, _spawn functions

Example

/* FPRESET.C: This program uses signal to set up a routine for handling

* floating-point errors.

*/

#include <stdio.h>

#include <signal.h>

#include <setjmp.h>

#include <stdlib.h>

#include <float.h>

#include <math.h>

#include <string.h>

jmp_buf mark; /* Address for long jump to jump to */

int fperr; /* Global error number */

void fphandler( int sig, int num ); /* Prototypes */

void fpcheck( void );

void main( void )

{

double n1, n2, r;

int jmpret;

/* Set up floating-point error handler. The compiler

* will generate a warning because it expects

* signal-handling functions to take only one argument.

*/

if( signal( SIGFPE, fphandler ) == SIG_ERR )

{

fprintf( stderr, "Couldn't set SIGFPE\n" );

abort();

}

/* Save stack environment for return in case of error. First time

* through, jmpret is 0, so true conditional is executed. If an

* error occurs, jmpret will be set to -1 and false conditional

* will be executed.

*/

jmpret = setjmp( mark );

if( jmpret == 0 )

{

printf( "Test for invalid operation - " );

printf( "enter two numbers: " );

scanf( "%lf %lf", &n1, &n2 );

r = n1 / n2;

/* This won't be reached if error occurs. */

printf( "\n\n%4.3g / %4.3g = %4.3g\n", n1, n2, r );

r = n1 * n2;

/* This won't be reached if error occurs. */

printf( "\n\n%4.3g * %4.3g = %4.3g\n", n1, n2, r );

}

else

fpcheck();

}

/* fphandler handles SIGFPE (floating-point error) interrupt. Note

* that this prototype accepts two arguments and that the prototype

* for signal in the run-time library expects a signal handler to

* have only one argument.

*

* The second argument in this signal handler allows processing of

* _FPE_INVALID, _FPE_OVERFLOW, _FPE_UNDERFLOW, and _FPE_ZERODIVIDE

* all of which are Microsoft-specific symbols that augment the

* information provided by SIGFPE. The compiler will generate a

* warning, which is harmless and expected.

*/

void fphandler( int sig, int num )

{

/* Set global for outside check since we don't want

* to do I/O in the handler.

*/

fperr = num;

/* Initialize floating-point package. */

_fpreset();

/* Restore calling environment and jump back to setjmp. Return -1

* so that setjmp will return false for conditional test.

*/

longjmp( mark, -1 );

}

void fpcheck( void )

{

char fpstr[30];

switch( fperr )

{

case _FPE_INVALID:

strcpy( fpstr, "Invalid number" );

break;

case _FPE_OVERFLOW:

strcpy( fpstr, "Overflow" );

break;

case _FPE_UNDERFLOW:

strcpy( fpstr, "Underflow" );

break;

case _FPE_ZERODIVIDE:

strcpy( fpstr, "Divide by zero" );

break;

default:

strcpy( fpstr, "Other floating point error" );

break;

}

printf( "Error %d: %s\n", fperr, fpstr );

}

Output

Test for invalid operation - enter two numbers: 5 0

Error 131: Divide by zero