Code (t125.c):
#include <fenv.h>
#include <stdint.h>
#include <stdio.h>
#if _MSC_VER
#pragma fenv_access (on)
#else
#pragma STDC FENV_ACCESS ON
#endif
void show_fe_exceptions(void)
{
printf("exceptions raised: ");
if (fetestexcept(FE_DIVBYZERO)) printf(" FE_DIVBYZERO");
if (fetestexcept(FE_INEXACT)) printf(" FE_INEXACT");
if (fetestexcept(FE_INVALID)) printf(" FE_INVALID");
if (fetestexcept(FE_OVERFLOW)) printf(" FE_OVERFLOW");
if (fetestexcept(FE_UNDERFLOW)) printf(" FE_UNDERFLOW");
if (fetestexcept(FE_ALL_EXCEPT)==0) printf(" none");
printf("\n");
}
typedef union { uint32_t u; float f; } ufloat;
int main(void)
{
_Bool b;
ufloat uqnan;
volatile float f;
uqnan.u = 0x7fc00000;
f = uqnan.f;
b = f == f;
show_fe_exceptions();
return b ? 1 : 0;
}
Invocations:
$ gcc t125.c -Wall -Wextra -pedantic -std=c17 && ./a.exe
t125.c:7: warning: ignoring ‘#pragma STDC FENV_ACCESS’ [-Wunknown-pragmas]
7 | #pragma STDC FENV_ACCESS ON
|
exceptions raised: none
$ clang t125.c -Wall -Wextra -pedantic -std=c17 && ./a.exe
t125.c:7:14: warning: pragma STDC FENV_ACCESS ON is not supported, ignoring pragma [-Wunknown-pragmas]
#pragma STDC FENV_ACCESS ON
^
1 warning generated.
exceptions raised: none
$ cl t125.c /fp:strict /std:c17 && t125
exceptions raised: none
Question: why QNAN == QNAN
does not lead to raising FE_INVALID
exception?
UPD. Reason of the question: (false, see below) assumption that <any_NAN> == <any_NAN>
leads to raising FE_INVALID
exception.
UPD2. Changed code: from f = *(float*)&qnan
to f = uqnan.f
(type punning via union). This is to avoid violation of the aliasing rules of the C standard.
ISO/IEC 9899:2011 (E) (emphasis added):
5.2.4.2.2 Characteristics of floating types <float.h>
3 A quiet NaN propagates through almost every arithmetic operation without raising a floating-point exception; a signaling NaN generally raises a floating-point exception when occurring as an arithmetic operand.
See also: What is the difference between quiet NaN and signaling NaN?.
UPD. Yes, it seems that equality does not count as an arithmetic operation for this purpose. Then here is a quote from IEEE 754-2008 (emphasis added):
5.11 Details of comparison predicates Programs that explicitly take account of the possibility of quiet NaN operands may use the unordered-quiet predicates in Table 5.3 which do not signal such an invalid operation exception.
For example, the predicate LT EQ
shall not lead to raising invalid operation exception. However, we see (in the comments above) that for f <= f
both gcc
and cl (msvc)
raise FE_INVALID
. Is it a bug / defect? Though none of them define __STDC_IEC_559__
with definition of 1. However, they are not required:
__STDC_IEC_559__
The integer constant 1, intended to indicate conformance to the specifications in annex F (IEC 60559 floating-point arithmetic).