In standard C (I mean C99 or C11) we have the so-called integer constant expressions, which are constant expressions whose operands are all constant integers. There are other constraints, as to avoid comma operators in the expression.
However, other non-integer objects (even non-constant) are allowed in some special cases.
For example, if the sizeof
operator is applied to an object whose size is known in translation time, this is allowed as part of an integer constant expression (note that sizeof
always return an integer value).
Moreover, the explicit cast to an integer type is sometimes allowed too.
The standard C99 establish the following rule:
Standard C99, Section 6.6(par.6):
An integer constant expression) shall have integer type and shall only have operands that are integer costants, enumeration constants, character constants, sizeof expressions whose results are integer constants, and floating constants that are the immediate operands of casts.
My question is: Which is the exact meaning of "floating constants that are the immediate operands of casts"?
A floating constant is something like 3.14e+3, or well 0x2.11p-5.
That is, is not a general constant expression of type float, but only a floating point literal.
Then, I understand that only something like this is allowed in the definition above:
(int) 3.14
but are not allowed operations involving floating literals.
This exclude cases as the following:
(int) -3.14 /* The minus sign is not part of the constant: it is an operator */
(int) (3.14) /* The parenthesis are an operator acting on the literal 3.14 */
The last case does not need to perform any floating point arithmetical operations in translation time, and it is equivalent to have the same without parenthesis: (int) 3.14
.
However, it is not the immediate operand of a cast.
So, do we have to consider that (int) (3.14)
is [part of] a valid integer constant expression or not (according to definition)?
On the other hand, the compiler GCC (with options: -std=c99 -pedantic-errors) gives me that (int) (3.14)
is a valid integer constant expression, for example in a declaration as the following:
#define BITW (int) (3.14)
struct { unsigned bitfield: BITW } test; // Translation success
(However, by doing #define BITW (int) (+3.14)
it fails to translate, as expected).
sizeof
, it's a compile-time only operator, so it's always an "integer constant expression". I don't think there's any type whose size could not be an integer. – Shaggysizeof
in an integer constant expression. – Periclessizeof
of an object whose size is known at compile-time is certainly not "non-constant". – Orinsizeof
can be a non-integer-constant-expression. For example, in:const int n = 42; sizeof(char[n]);
the result of not an integer constant expression becausechar[n]
has VLA type (even thoughn
is known at compile time). – Monkishsizeof(…)
is constant, it's never considered a constant." (My guess is that legacy considerations alone would prevent that, what with VLAs being a later addition.) – Orinsign-part
corresponds only to theexponent-part
of the floating constant. – Periclesfloating constant
, you cannot use negative values anywhere a floating constant is required? That seems like a deficiency in the standard, and one most likely only honoured in the breach. – Upspring