Оценка короткого замыкания и побочные эффекты
Хорошо, я немного смущен, чтобы задать этот вопрос, но я просто хочу быть уверен...
Известно, что C использует оценку короткого замыкания в логических выражениях:
int c = 0;
if (c && func(c)) { /* whatever... */ }
В этом примере func(c)
не называется, потому что c
оценивает 0
, Но как насчет более сложного примера, в котором побочные эффекты сравнения могут изменить следующую сравниваемую переменную? Как это:
int c; /* this is not even initialized... */
if (canInitWithSomeValue(&c) && c == SOMETHING) { /*...*/ }
функция canInitWithSomeValue
возвращает true и изменяет значение по указанному указателю в случае успеха. Гарантируется ли последующее сравнение (c == SOMETHING
в этом примере) использует значение, установленное canInitWithSomeValue(&c)
?
Независимо от того, насколько тяжелые оптимизации использует компилятор?
3 ответа
Гарантируется ли, что в последующих сравнениях (в этом примере c == SOMETHING) используется значение, установленное canInitWithSomeValue(&c)?
Да. Потому что есть точка последовательности
Между оценкой левого и правого операндов
&&
(логическое И),||
(логическое ИЛИ) и операторы запятой. Например, в выражении*p++ != 0 && *q++ != 0
все побочные эффекты под-выражения *p++!= 0 завершаются до любой попытки доступа к q.
Точка последовательности определяет любую точку выполнения компьютерной программы, при которой гарантируется, что все побочные эффекты предыдущих оценок будут выполнены, и никаких побочных эффектов от последующих оценок еще не было выполнено.
Да. Потому что оба &&
а также ||
Операторы также называются точками последовательности. Последние определяют, когда побочные эффекты предыдущей операции должны быть завершены, а побочные эффекты следующей не должны были начаться.
Оценка в составном условии оператора if строго слева направо. Единственное обстоятельство, при котором второй тест в вашем if будет оптимизирован, - это если компилятор может с 100% уверенностью определить, что первый тождественно равен false.