Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Details of what constitutes a constant expression in C?

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

  • constant expression (unqualified)
  • arithmetic constant expression
  • integer 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.

like image 544
R.. GitHub STOP HELPING ICE Avatar asked Feb 04 '11 00:02

R.. GitHub STOP HELPING ICE


People also ask

What is a constant expression?

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.

What are the 3 constants used in C?

Primary constants − Integer, float, and character are called as Primary constants. Secondary constants − Array, structures, pointers, Enum, etc., called as secondary constants.

What are constants list the types of constants as defined in C language?

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.


1 Answers

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.

like image 160
Chris Lutz Avatar answered Oct 04 '22 12:10

Chris Lutz