Операционная система
Что касается переключателя, в стандарте указано следующее. "Когда выполняется оператор switch, его состояние оценивается и сравнивается с каждой константой случая".
Означает ли это, что выражение условия оценивается один раз и один раз, и оно гарантируется стандартом для каждого компилятора?
Например, когда функция используется в заголовке оператора switch с побочным эффектом.
int f() { ... }
switch (f())
{
case ...;
case ...;
}
Ответы
Ответ 1
Я думаю, что гарантировано, что f
вызывается только один раз.
Сначала мы имеем
Условие должно быть целым типом, типом перечисления или типом класса.
[6.4.2 (1)] (здесь не применяется неотмеченный материал) и
Значение условия, являющегося выражением, является значением Выражение
[6.4 (4)]. Кроме того,
Значение условия будет называться просто "условием", в котором использование недвусмысленно.
[6.4 (4)] Это означает, что в нашем случае "условие" является просто равным значением типа int
, а не f
. f
используется только для определения значения условия. Теперь, когда управление достигает инструкции switch
его условие оценивается
[6.4.2 (5)], т.е. мы используем значение int
, которое возвращается f
как наше "условие". Тогда, наконец, условие (которое является значением типа int
, а не f
), равно
по сравнению с каждой константой случая
[6.4.2 (5)]. Это не вызовет побочные эффекты от f
снова.
Все цитаты из N3797. (Также проверено N4140, нет разницы)
Ответ 2
Чтение N4296
Page 10 para 14:
Каждое вычисление значения и побочный эффект, связанные с полным выражением, секвенируются перед каждым значением вычисление и побочный эффект, связанные со следующим полным выражением, которое должно быть оценено.
Когда я прочитал первую строку параграфа. 10 (выше этого):
Полное выражение - это выражение, которое не является подвыражением другое выражение.
Я должен полагать, что условие оператора switch
является полным выражением, а каждое выражение условия является полным выражением (хотя и тривиальным при выполнении).
A switch
- это выражение, а не выражение (см. 6.4.2 и многие другие места).
Таким образом, при этом чтении оценка switch
должна выполняться перед оценкой констант case
.
Как всегда многие точки сводятся к извилистому чтению спецификации, чтобы прийти к очевидному выводу.
Если я рассмотрю это предложение, я бы предложил следующую поправку (в жирный):
Когда оператор switch выполняется, его состояние оценивается один раз за выполнение оператора switch и сравнивается с каждой константой случая.
Ответ 3
Да выражение оценивается только один раз, когда выполняется оператор switch:
§ 6.4 Операции выбора
4 [...] Значение условия, являющегося выражением, является значением выражение [...] Значение условия будет называться просто "условием", где использование недвусмысленно.
Это означает, что выражение оценивается, и его значение считается condition
, которое должно быть оценено против каждого оператора case
.
Ответ 4
Раздел 6.4.4:
... Значение условия, являющегося выражением, является значением выражение, контекстно преобразованное в bool для операторов, отличных от switch;... Значение условия будет называться просто "условием", в котором использование недвусмысленно
В моем понимании приведенная выше цитата эквивалентна следующему псевдокоду:
switchCondition := evaluate(expression)
Теперь добавьте свою цитату
... его состояние оценивается и сравнивается с каждой константой случая.
Который должен быть переведен на:
foreach case in cases
if case.constant == switchCondition
goto case.block
Так что да, похоже, это так.
Ответ 5
Этот код печатает hello
один или два раза?
int main() {
printf("hello\n");
}
Хорошо, я думаю, что ответ заключается в более общем понимании того, что описывает стандарт, а не в конкретной формулировке формулировки switch
.
В соответствии с Исполнением программы [intro.execution] стандарт описывает поведение какой-либо абстрактной машины, которая выполняет программу, анализированную по грамматике С++. Он не определяет, что означает "абстрактная машина" или "выполняет", но предполагается, что они означают их очевидные концепции компьютерной науки, то есть компьютер, который проходит через абстрактное синтаксическое дерево и оценивает каждую его часть в соответствии с семантикой, описанной в стандарт. Это означает, что если вы что-то написали один раз, то, когда выполнение дойдет до этой точки, оно оценивается только один раз.
Более актуальным вопросом является "когда реализация может оценивать что-то не так, как написано в программе"? Для этого существует правило as-if и куча поведения undefined, которые позволяют реализации отклоняться от этой абстрактной интерпретации.
Ответ 6
Выражение гарантировано, которое оценивается только один раз потоком управления. Это оправдано в стандарте N4431 §6.4.2/6. Оператор switch [stmt.switch] (Активный удар):
case и метки по умолчанию сами по себе не изменяют поток который продолжает беспрепятственно проходить через такие метки. Чтобы выйти из переключатель, см. разрыв, 6.6.1. [Примечание: обычно, субстанция, которая предмет переключателя является составным и случайным, и появляются метки по умолчанию на операторах верхнего уровня, содержащихся в (составной) субстанция, но это не требуется. Объявления могут появляться в подстановка оператора switch-statement. - конечная нота]