Is it possible to have the compiler error/warning diagnostic output a compile-time computed numeric value in C11 or C17 (i.e. not using templates)? The below link does this in C++ using template magic. The intention is to use this as a _Static_assert replacement which prints the values of the non-equal failed expression. Ideally, it should be able to evaluate the expression as true or false, and print only when it fails evaluation.
This is obviously compiler-dependent, so assume GCC.
Building off the answers of Lundin and Tavian, the generic solution macro for positive and negative values is as follows:
#define STATIC_ASSERT_EQUAL(VALUE, EXPECTED) \
(void)_Generic(&(char[(EXPECTED) > 0 ? (VALUE) : (EXPECTED) < 0 ? \
-(VALUE) : (VALUE) == 0 ? 0x7FFFFFFF : (VALUE)]){0}, \
char(*)[(EXPECTED) > 0 ? (EXPECTED) : (EXPECTED) < 0 ? \
-(EXPECTED) : 0x7FFFFFFF] : 0)
The macro must be used inside a function. The idea is that EXPECTED is a value known by the programmer, and VALUE is the unknown calculated value. This was tested with GCC 6.1.
These pass without error:
STATIC_ASSERT_EQUAL(-1, -1);
STATIC_ASSERT_EQUAL(0, 0);
STATIC_ASSERT_EQUAL(1, 1);
However, this also unfortunately passes without error, because 0 aliases with 0x7FFFFFFF:
STATIC_ASSERT_EQUAL(0x7FFFFFFF, 0);
The error case appears as:
STATIC_ASSERT_EQUAL(2, 1);
error: ‘_Generic’ selector of type ‘char (*)[2]’ is not compatible with any association
If you have certain warnings enabled:
STATIC_ASSERT_EQUAL(0, 1);
error: ISO C forbids zero-size array [-Werror=pedantic]
Since EXPECTED is not 0, then the programmer can assume VALUE == 0.
STATIC_ASSERT_EQUAL(-2, 1);
error: size of unnamed array is negative
The value is not displayed in this case, but the programmer can see the VALUE is negative when it shouldn't be, so negate VALUE, and it will display.
STATIC_ASSERT_EQUAL(2, -1);
error: size of unnamed array is negative
Similarly for above, the programmer knows the VALUE should be negative, but isn't, so negating VALUE will make it display.
STATIC_ASSERT_EQUAL(-2, -1);
error: ‘_Generic’ selector of type ‘char (*)[2]’ is not compatible with any association
The programmer knows it should be negative, and here it displays the positive equivalent of VALUE.
STATIC_ASSERT_EQUAL(2, 0);
error: ‘_Generic’ selector of type ‘char (*)[2]’ is not compatible with any association
The above zero case works as expected.