Оценка короткого замыкания и побочные эффекты

Хорошо, я немного смущен, чтобы задать этот вопрос, но я просто хочу быть уверенным...

Известно, что 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)?

Независимо от того, насколько сложны оптимизаторы, используемые компилятором?

Ответ 1

Гарантировано ли, что последующие сравнения (c == SOMETHING в этом примере) используют значение, установленное canInitWithSomeValue (& c)?

Да. Потому что есть точка последовательность

Между оценкой левого и правого операндов && (логическое И), || (логическое ИЛИ) и запятыми. Например, в выражении *p++ != 0 && *q++ != 0 все побочные эффекты подвыражения * p ++!= 0 завершены до любой попытки доступа к q.


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

Ответ 2

Да. Потому что оба оператора && и || также называются точками последовательности. Последние определяют, когда побочные эффекты предыдущей операции должны быть полными, а побочные эффекты следующего не должны начаться.

Ответ 3

Оценка в составном условии оператора if строго слева направо. Единственное обстоятельство, при котором второй тест в вашем if будет оптимизирован, - это если компилятор может определить со 100% уверенностью, что первый идентично равен false.