Почему «Каждое константное выражение должно иметь значение...» вместо «Каждое вычисленное константное выражение должно иметь значение...»?

n3301, 6.6 Константные выражения, п4 (выделено нами):

Каждое константное выражение должно оценивать константу, находящуюся в диапазоне представимых значений для его тип.

n3301, 6.5.15 Логический оператор ИЛИ, p4 (выделено нами):

Если первый операнд при сравнении не равен 0, второй операнд не оценивается.

Вопрос: почему 1-е требование не зависит от требования вычисления (или невычисления) такого константного выражения?

Другими словами: почему «Каждое константное выражение должно иметь значение...» вместо «Каждое вычисленное константное выражение должно иметь значение...»?

Это упущение?


Причина вопроса: некоторые люди считают, что «Каждое константное выражение должно иметь значение...» имеет приоритет (т. е. более сильное, имеет больший приоритет) над «вторым операндом не оценивается».

Да, у n3301 есть сноска 119:

  1. Таким образом, при следующей инициализации
static int i = 2 || 1 / 0;

выражение является допустимым целочисленным константным выражением со значением один.

Однако «В стандартах ISO примечания без исключения являются ненормативными.»

🤔 А знаете ли вы, что...
C имеет богатую стандартную библиотеку, включающую функции для работы с файлами, строками, памятью и другими задачами.


1
74
2

Ответы:

Решено

Цитата, о которой идет речь, является частью определения константного выражения. Правило грамматики используется в тех местах, где ожидается, что код будет оцениваться во время компиляции. Это означает, что константные выражения обычно оцениваются безоговорочно (во время компиляции). Введение концепции константного выражения, которое не вычисляется, бесполезно и ненужно.


2 || 1 / 0 является допустимым константным выражением, поскольку это допустимое условное выражение, удовлетворяющее ограничениям константного выражения.

Соответственно, его значение равно 1, поэтому оно «вычисляет константу, находящуюся в диапазоне представимых значений для своего типа».

Оценка 2 || 1 / 0 не оценивает 1 / 0, но это не значит, что 2 || 1 / 0 нельзя оценить.

Следовательно, 2 || 1 / 0 можно использовать там, где ожидается константное выражение. Например, case 2 || 1 / 0 допустимо (хотя и довольно странно).

Демо в Compiler Explorer.


Хотя 1 / 0 является допустимым условным выражением, оно не соответствует ограничениям константного выражения, поэтому оно не является допустимым константным выражением.

В частности, он не «вычисляет константу, находящуюся в диапазоне представимых значений для ее типа».

Следовательно, 1 / 0 нельзя использовать там, где ожидается константное выражение. Например, case 1 / 0 недопустимо.

Демо в Compiler Explorer.


Часть вопроса заключается в том, каково постоянное выражение в (ненормативном) примечании:

статический int я = 2 || 1/0;

Если это все выражение i = 2 || 1 / 0, то его можно вычислить, поскольку правило сокращения слева направо (что в a || b, если a истинно, то b не оценивается) означает, что константное выражение действительно оценивается как константа в представимом диапазоне.

И это несмотря на то, что подвыражение 1 / 0 не может быть вычислено (вообще), не говоря уже о константе, которую можно представить...

Я понимаю точку зрения ОП. Я думаю, что делаю вывод, что постоянное выражение — это вся правая часть присваивания. Это полезная интерпретация.

Я не думаю, что спецификация не совсем понимает, что такое постоянное выражение. Помогло бы что-то вроде «Константное выражение — это выражение, которое может быть вычислено во время перевода», и это отличается от «Константное выражение может быть вычислено во время перевода». Я читаю «можно» в отличие от «есть», «должен» или даже «должен».

Спецификация далее определяет константные выражения и даже допускает расширения, зависящие от реализации.

Там также говорится: «Семантические правила для вычисления постоянного выражения такие же, как и для непостоянного выражения». выражения». и содержит (ненормативное) примечание к приведенному выше примеру.

Но педантично, что (по крайней мере, в принципе) это не противоречит тому, что (суб-)выражение 1/0 квалифицируется как постоянное выражение.

Это определенно вопрос языкового юриста, потому что я думаю, что люди, знакомые с C, знают намерение авторов, вопрос в том, достигли ли они его совершенно однозначно и точно.