C defines at least 3 levels of "constant expression":
6.6 paragraph 3 reads:
Constant expressions shall not contain assignment, increment, decrement, function-call, or comma operators, except when they are contained within a subexpression that is not evaluated.
So does this mean 1,2
is not a constant expression?
Paragraph 8 reads:
An arithmetic constant expression shall have arithmetic type and shall only have operands that are integer constants, floating constants, enumeration constants, character constants, and sizeof expressions. Cast operators in an arithmetic constant expression shall only convert arithmetic types to arithmetic types, except as part of an operand to a sizeof operator whose result is an integer constant.
What are the operands in (union { uint32_t i; float f; }){ 1 }.f
? If 1
is the operand, then this is presumably an arithmetic constant expression, but if { 1 }
is the operand, then it's clearly not.
Edit: Another interesting observation: 7.17 paragraph 3 requires the result of offsetof
to be an integer constant expression of type size_t
, but the standard implementations of offsetof
, as far as I can tell, are not required to be integer constant expressions by the standard. This is of course okay since an implementation is allowed (under 6.6 paragraph 10) to accept other forms of constant expressions, or implement the offsetof
macro as __builtin_offsetof
rather than via pointer subtraction. The essence of this observation, though, is that if you want to use offsetof
in a context where an integer constant expression is required, you really need to use the macro provided by the implementation and not roll your own.
A constant expression is an expression that can be evaluated at compile time. Constants of integral or enumerated type are required in several different situations, such as array bounds, enumerator values, and case labels. Null pointer constants are a special case of integral constants.
Primary constants − Integer, float, and character are called as Primary constants. Secondary constants − Array, structures, pointers, Enum, etc., called as secondary constants.
Character Constants One or more characters are enclosed within a single quote (' ') or ("") depending on the type of characters. Character constants having a single character enclosed within the ' ' (Single quote) are known as character constants. Example: 's', 'c', 'a', 'l', 'e', 'r', etc.
Based on your reading, 1,2
isn't a constant expression. I don't know why it isn't, just that I agree with you that it isn't (despite the fact that it probably should be).
6.5.2 specifies compound literals as a postfix operator. So in
(union { uint32_t i; float f; }){ 1 }.f
The operands are (union { uint32_t i; float f; }){ 1 }
and f
to the .
operator. It is not an arithmetic constant expression, since the first argument is a union
type, but it is a constant expression.
UPDATE: I was basing this on a different interpretation of the standard.
My previous reasoning was that (union { uint32_t i; float f; }){ 1 }.f
met the criteria for a constant expression, and was therefore a constant expression. I still think it meets the criteria for a constant expression (6.6 paragraph 3) but that it is not any of the standard types of constant expressions (integer, arithmetic, or address) and is therefore only subject to being a constant expression by 6.6 paragraph 10, which allows implementation-defined constant expressions.
I'd also been meaning to get to your edit. I was going to argue that the "hack" implementation of offsetof
was a constant expression, but I think it's the same as above: it meets the criteria for a constant expression (and possibly an address constant) but is not an integer constant expression, and is therefore invalid outside of 6.6 paragraph 10.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With