The recent (C23) addition of stdckdint.h
provides a portable way to check for overflow problems in integer arithmetic. I have used similar compiler extensions in the past in cases where the integers in question are provided by the user and they have been very helpful. Right now I faced with a situation where the values provided are floating point numbers instead, and I need to do arithmetic operations with them.
My question is whether there is a similar solution (not necessarily in the standard library), to ensure that operations between floating point variables (floats, doubles, long doubles) won't run into any issues. If not, what are all the possible problems that might occur during arithmetic operations (overflows, underflows, etc.) and how can I check for them?
If not, what are all the possible problems that might occur during arithmetic operations (overflows, underflows, etc.)…
Omitting discussion of C conformance, both of the standard and of implementations, to the IEEE 754 floating-point standard, IEEE 754 specifies five kinds of exceptions in clause 7:
In this context, “signaled” means the exception is indicted in some means, such as setting a bit in a status register. It does not mean program execution is interrupted or altered, as when a Unix signal causes a signal handler to be executed. The above is a summary and omits some details.
… If not, what are all the possible problems that might occur during arithmetic operations (overflows, underflows, etc.) and how can I check for them?
The current C standard, 2018, and the forthcoming standard, if faithful to the available drafts, provide facilities for testing floating-point exceptions in clause 7.6, discussing the header <fenv.h>
and its associated facilities. Testing for exceptions is specified in 7.6.4.
feclearexcept(FE_ALL_EXCEPT)
attempts to clear all supported exception flags and returns zero iff succesful.
fetestexcept(mask)
returns the bitwise AND of mask
and the exception flags that are set. The mask may be a bitwise OR of FE_DIVBYZERO
, FE_INEXACT
, FE_INVALID
, FE_OVERFLOW
, FE_UNDERFLOW
, and possibly other flag names supported by the particular C implementation.
Testing exceptions in this way may be slow, depending on the C implementation and its underlying hardware, because it may require accessing a status register in a way that interrupts processor execution of instructions or because it requires the compiler to use scalar floating-point instructions when it might have optimized to using SIMD instructions if the flags were not being accessed. Some C implementations may provide alternate methods of testing flags. In particular, for performance, it may be preferable not to test flags explicitly but rather to set exception handlers to be triggered when an exception occurs. This can be useful for detecting exceptions you expect to be rare, such as overflows with code designed to avoid them. However, with exceptions that are common, such as inexact (normally common) or underflow (not uncommon in some code, such as diminishing echo effects), frequent execution of exception handlers will impair performance.