Alex Celeste
Alex Celeste

Reputation: 13380

Is indexing a string literal an initializer constant expression?

The following code attempts to use array indexing on a string literal in two different constant contexts:

static char x = "abcx"[3];

_Static_assert ("abcx"[3] == 'x', "...");

Judging by Compiler Explorer, there's clear consensus among tool vendors that doing this in the second context, which explicitly requires an integer constant expression, is not allowed. However, they seem to differ about the first context, which is only an arithmetic constant expression used in an initializer. GCC and Clang stand out as implementations which permit this.

By itself this isn't interesting because in paragraph 10 of 6.6, C11/C18 does say that "an implementation may accept other forms of constant expressions." However, it stands out in this case because:

The timing of the change in behaviour makes it look like this was something to do with C18, but the wording of 6.6 doesn't seem to have changed. The restrictions on integer constant expressions remain strict (as shown by the second line continuing to error), and the wording of paragraph 9 seems the same as it was in C11, in particular continuing to say that "the value of an object shall not be accessed by use of these operators" (w.r.t [] and friends).

Is the first context a valid initializer constant by any reading of the standard, not counting paragraph 10? Is there anywhere I would be likely to find a rationale for the GCC/Clang changes?

Upvotes: 12

Views: 386

Answers (1)

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215487

6.6 Constant expressions, ¶8:

An arithmetic constant expression shall have arithmetic type and shall only have operands that are integer constants, floating constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, and _Alignof 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 or _Alignof operator.

A string literal is not any of the above 6 operand types permitted, so the expression is not an arithmetic constant expression unless it's accepted as an extension.

Upvotes: 3

Related Questions