Case A: C11, 6.6 Constant expressions, Semantics, 5:
If a floating expression is evaluated in the translation environment, the arithmetic range and precision shall be at least as great as if the expression were being evaluated in the execution environment.116)
which requires the following program to return 0:
#include <float.h>
#define EXPR DBL_MIN * DBL_MAX
double d1 = EXPR;
double d2;
#pragma STDC FENV_ACCESS ON
int main(void)
{
d2 = EXPR;
return d1 == d2 ? 0 : 1;
}
Case B: C11, 6.10.1 Conditional inclusion, Semantics, 4:
Whether the numeric value for these character constants matches the value obtained when an identical character constant occurs in an expression (other than within a #if or #elif directive) is implementation-defined.168)
which does not require the following program to return 0:
#define EXPR 'z' - 'a' == 25
int main(void)
{
_Bool b1 = 0;
_Bool b2;
#if EXPR
b1 = 1;
#endif
b2 = EXPR;
return b1 == b2 ? 0 : 1;
}
Question: what is the rationale for making "Case B" implementation-defined behavior?
The C11 Standard (I shall be quoting from this draft document) defines two character sets:
Furthermore, there is no requirement that equivalent characters in those sets are represented by the same values, and neither is there any requirement that Latin letters are stored in sequence. So, in the example given, the value of
'z' - 'a'need not be the same in those two sets.Now, the order of translation phases specifies that macro invocations and evaluations (and other pre-processing directives) are performed using the source character set but expressions that occur in executable code are evaluated after conversion to the execution character set:
Thus, because the relationship between those character sets is implementation-defined, and because the two occurrences of the character-based constant expressions are defined to use different sets, the fact that they may have different evaluations must also be implementation-defined.