Details of what const constant expression is in C?

C defines at least 3 levels of "constant expression":

  • constant expression (unskilled)
  • expression of arithmetic constant
  • integer constant expression

6.6 clause 3 states:

Constant expressions must not contain assignment, increment, decrement, function call, or commas, except when they are contained in a subexpression that is not evaluated.

Does this mean that 1,2 not a constant expression?

Paragraph 8 states:

An arithmetic constant expression must have an arithmetic type and must have operands that are integer constants, current constants, enumeration constants, the nature of the constant, and the size of the expressions. Cast operators in an arithmetic constant expression should only convert arithmetic types to arithmetic types, except that part of the operand sizeof is an operator whose result is an integer constant.

What are the operands in (union { uint32_t i; float f; }){ 1 }.f ? If 1 is an operand, then this is a supposedly arithmetic constant expression, but if { 1 } is an operand, then this is clearly not.

Edit: Another interesting note: 7.17 paragraph 3 requires that the result of offsetof be an integer constant expression of type size_t , but the standard implementation of offsetof , as far as possible I can say, is not necessary to be integer constant expressions according to the standard. This, of course, is good, since the implementation is allowed (under clause 6.6 of clause 10) to take other forms of constant expressions or implement the offsetof macro as __builtin_offsetof , and not by subtracting the pointer. The point of this observation 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, rather than folding your own.

+8
c standards constants constant-expression
source share
2 answers

Based on your reading, 1,2 not a constant expression. I do not know why this is not so, I just agree with you that it is not (despite the fact that it probably should be).

6.5.2 indicates compound literals as a postfix operator. So in

 (union { uint32_t i; float f; }){ 1 }.f 

The operands (union { uint32_t i; float f; }){ 1 } and f refer to the operator . . This is not an arithmetic constant expression, since the first argument is a union type, but it is a constant expression.

UPDATE: I based this on a different interpretation of the standard.

My previous reasoning was that (union { uint32_t i; float f; }){ 1 }.f satisfies the criteria for a constant expression and, therefore, is a constant expression. I still think that it meets the criteria for a constant expression (6.6, clause 3), but that it is not a standard type of constant expressions (integer, arithmetic or address) and therefore is subject to a constant expression in clause 6.6 10, which allows the use of constant expressions defined by implementation.

I would also like to get to your editing. I would like to argue that the implementation of "hack" offsetof was a constant expression, but I think it is the same as above: it meets the criteria for a constant expression (and possibly a constant address), but is not an integer constant and therefore is invalid outside clause 6.6 clause.

+1
source share

If 1,2 is a constant expression, this will allow compilation of the following code:

 { // code // How the compiler interprets: int a[10, 10]; // int a[10]; a[5, 8] = 42; // a[8] = 42; } 

I do not know if this is the real reason, but I can imagine that the error in the error for this (general?) Error was considered more important than turning 1,2 into a constant expression.

UPDATE As R. points out in the commentary, the code stating that it is no longer a compiler error since the VLA appeared.

0
source share

All Articles