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

17

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

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

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

    
задан Łukasz Sromek 03.09.2010 в 14:31
источник
  • Я думаю, что вы можете ввести в заблуждение оценку короткого замыкания и оптимизацию компилятора. В первом примере компилятор оптимизирует этот весь оператор if, потому что он никогда не может работать. Оценка короткого замыкания означала бы, что если бы (func1 () && func2 ()) {...}, а func1 () оценивается как false во время выполнения (то есть не обязательно при компиляции), тогда код не должен проверять func2 () - компилятор должен был создать машинный код таким образом, что если func1 () является ложным, func2 () не вызывается. –  Stephen 03.09.2010 в 14:35
  • То, что int c = 0 указывало, что c равно 0 во время сравнения, я понимаю, что в случае, когда простой компилятор оптимизирует все if. –  Łukasz Sromek 03.09.2010 в 14:53
  • А, я извиняюсь. Я неправильно понял вас. Мои извинения. –  Stephen 03.09.2010 в 15:46

3 ответа

23
  

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

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

  

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

  

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

    
ответ дан Amarghosh 03.09.2010 в 14:35
  • отличный ответ, спасибо! –  Łukasz Sromek 03.09.2010 в 14:55
5

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

ответ дан dirkgently 03.09.2010 в 14:35
1

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

    
ответ дан Steve Townsend 03.09.2010 в 14:36