Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:

  • GCC and Clang are both accepting this silently with -pedantic (true, signoff by a compiler doesn't mean code is conforming). Building the code makes sense as its meaning is straightforward, but I would expect a warning if they thought this wasn't conforming, and they can recognize whether (they think) it is or not, because...

  • for both compilers, the behaviour has changed recently - Clang used to raise an error over this up until 3.8, while GCC used to raise an error up until 8.0. These versions came out in 2016 and 2018 respectively. This suggests the change was intentional, but I haven't yet found release notes for either compiler that go into this level of detail.

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?

like image 324
Leushenko Avatar asked Jun 15 '19 15:06

Leushenko


Video Answer


1 Answers

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.

like image 81
R.. GitHub STOP HELPING ICE Avatar answered Oct 19 '22 10:10

R.. GitHub STOP HELPING ICE