liveBook · Manning

Fenv.h

As explained in Modern C, Third Edition

fenv.h is the C standard header that provides access to the floating-point environment and its status and control facilities.

fenv.h provides access to the floating-point environment: exceptional conditions raised by floating-point operations and interfaces for inspecting or clearing them. Supported conditions commonly include division by zero, inexact results, invalid operations, overflow, and underflow. Availability and behavior depend on the platform, so numerical code should avoid operations that are not mathematically defined for its underlying type. section 15.1.1

Inspecting floating-point exceptions

Clear the environment before an operation, perform the operation, then call fetestexcept to query FE_ALL_EXCEPT. The returned flags can be decoded by testing individual FE_* values; call feclearexcept again before the next independent measurement. section 15.1.1

 int excepts[] = {
 #ifdef FE_DIVBYZERO
   FE_DIVBYZERO,
 #endif
 #ifdef FE_INEXACT
   FE_INEXACT,
 #endif
 #ifdef FE_INVALID
   FE_INVALID,
 #endif
 #ifdef FE_OVERFLOW
   FE_OVERFLOW,
 #endif
 #ifdef FE_UNDERFLOW
   FE_UNDERFLOW,
 #endif
 };

Builds a portable list of available FE_* exception flags by conditionally including macros supported by the implementation. section 15.1.1

 void printexcept(void) {
   char const* name[] = {
 #ifdef FE_DIVBYZERO
     "divbyzero",
 #endif
 #ifdef FE_INEXACT
     "inexact",
 #endif
 #ifdef FE_INVALID
     "invalid",
 #endif
 #ifdef FE_OVERFLOW
     "overflow",
 #endif
 #ifdef FE_UNDERFLOW
     "underflow",
 #endif
   };
   int except = fetestexcept(FE_ALL_EXCEPT);
   if (except) {
     printf("[");
     for (unsigned j = 0; except; except &= ~excepts[j], ++j)
       if (excepts[j] & except)
         printf("%s ", name[j]);
     printf("]");
   }
 }
 
 int main (int argc, char* argv[static argc+1]) {
   printf("division by zero is %sequal to INFINITY\n", has_inf ? "" : "un");
   for (unsigned i = 1; i < argc; i++) {
     feclearexcept(FE_ALL_EXCEPT);
     double x = strtod(argv[i], nullptr);
     printf("%g ", x);
     printexcept();
     feclearexcept(FE_ALL_EXCEPT);
     printf(": %g ", 1.0/x);
     printexcept();
     puts("");
   }
 }

Demonstrates clearing exceptions, converting command-line input, testing flags, and reporting conditions raised by division. section 15.1.1

How Modern C, Third Edition covers it

How deep it goes
Defines exception flags and demonstrates testing and clearing them, but defers broader floating-point environment control.
Examples
Uses conditional FE_* flag arrays and a program that reports exceptions before and after division.
What it assumes
Assumes familiarity with C arithmetic and macros while teaching platform-dependent floating-point exceptions from their operational consequences.
What you can do after
Diagnose/debug with it by clearing, testing, and decoding floating-point exception flags around operations.
How it connects
Connects floating-point arithmetic with division by zero, infinity, exceptional conditions, and platform portability.

This explainer was generated by Manning's knowledge graph from the text of Modern C, Third Edition. The section links point to the parts of the book it draws on.