n3301, 6.6 Константные выражения, п4 (выделено нами):
Каждое константное выражение должно оценивать константу, находящуюся в диапазоне представимых значений для его тип.
n3301, 6.5.15 Логический оператор ИЛИ, p4 (выделено нами):
Если первый операнд при сравнении не равен 0, второй операнд не оценивается.
Вопрос: почему 1-е требование не зависит от требования вычисления (или невычисления) такого константного выражения?
Другими словами: почему «Каждое константное выражение должно иметь значение...» вместо «Каждое вычисленное константное выражение должно иметь значение...»?
Это упущение?
Причина вопроса: некоторые люди считают, что «Каждое константное выражение должно иметь значение...» имеет приоритет (т. е. более сильное, имеет больший приоритет) над «вторым операндом не оценивается».
Да, у n3301 есть сноска 119:
- Таким образом, при следующей инициализации
static int i = 2 || 1 / 0;
выражение является допустимым целочисленным константным выражением со значением один.
Однако «В стандартах ISO примечания без исключения являются ненормативными.»
🤔 А знаете ли вы, что...
C имеет богатую стандартную библиотеку, включающую функции для работы с файлами, строками, памятью и другими задачами.
Цитата, о которой идет речь, является частью определения константного выражения. Правило грамматики используется в тех местах, где ожидается, что код будет оцениваться во время компиляции. Это означает, что константные выражения обычно оцениваются безоговорочно (во время компиляции). Введение концепции константного выражения, которое не вычисляется, бесполезно и ненужно.
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, знают намерение авторов, вопрос в том, достигли ли они его совершенно однозначно и точно.