Является ли индексирование строкового литерала константным выражением инициализатора? - PullRequest
11 голосов
/ 15 июня 2019

Следующий код пытается использовать индексирование массива для строкового литерала в двух разных константных контекстах:

static char x = "abcx"[3];

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

Судя по Compiler Explorer, среди поставщиков инструментов есть четкое согласие с тем, что делать это во втором контексте, для которого явно требуется целочисленное константное выражение , недопустимо. Однако, похоже, что они отличаются в первом контексте, который является выражением арифметической константы , используемым в инициализаторе. GCC и Clang выделяются как реализации, которые позволяют это.

Само по себе это не интересно, потому что в * 10 10 * параграфе 6 6.6 C11 / C18 действительно говорит, что «реализация может принимать другие формы константных выражений». Тем не менее, это выделяется в этом случае, потому что:

  • GCC и Clang оба принимают это молча с помощью -pedantic (правда, завершение компилятором не означает, что код соответствует). Построение кода имеет смысл, так как его значение простое, но я бы ожидал предупреждения, если бы они думали, что это не соответствует, и они могут понять, действительно ли (они думают) это или нет, потому что ...

  • для обоих компиляторов поведение недавно изменилось - Clang использовал для повышения ошибки до 3.8, в то время как GCC использовал для повышения ошибки до 8.0. Эти версии вышли в 2016 и 2018 годах соответственно. Это говорит о том, что изменение было преднамеренным , но я еще не нашел примечаний к выпуску ни для одного из компиляторов, которые бы подходили к этому уровню детализации.

Время изменения поведения позволяет понять, что это связано с C18, но формулировка 6.6, похоже, не изменилась. Ограничения для целочисленных константных выражений остаются строгими (как показано во второй строке с ошибкой), и формулировка пункта 9 кажется такой же, как и в C11, в частности, продолжая говорить, что «значение объекта нельзя использовать с помощью этих операторов "(wrt [] и друзья).

Является ли первый контекст допустимой константой инициализатора при любом чтении стандарта, не считая параграфа 10? Могу ли я найти обоснование изменений в GCC / Clang?

1 Ответ

2 голосов
/ 15 июня 2019

6.6 Выражения констант, ¶8:

Выражение арифметической константы должно иметь арифметический тип и иметь только операнды, которые являются целочисленными константами , плавающими константами , константы перечисления , символьные константы , размер выражений , результатом которых являются целочисленные константы, и _Alignof выражений .Операторы приведения в выражении арифметической константы должны преобразовывать только арифметические типы в арифметические типы, кроме как как часть операнда, к оператору sizeof или _Alignof.

Строковый литерал не является ни одним из вышеуказанных 6 типов операндов.разрешено, поэтому выражение не является выражением арифметической константы, если оно не принято как расширение.

...