Оператор &&
вычисляется лениво.
Если node != NULL
равно false, has_all_except
даже не будет учитываться. Это правило языка, а не оптимизация.
Зацикливание безоговорочно, если ни один из них не был изменен, теоретически возможно, в зависимости от того, откуда они могли быть изменены и насколько легко это определить. Я подозреваю, однако, что это возможно хуже для современного процессора, чем просто применение тестов. (Это приведет к большему количеству ветвлений, большему количеству кода и увеличению требований к памяти - с другой стороны, предсказание ветвлений должно хорошо работать при управлении циклами, например).
Вы можете реализовать этот вид «оптимизации» самостоятельно, используя goto
для проверки этого (примечание: я не рекомендую использовать goto
, но он переносимо «симулирует» эффект предлагаемой обсуждаемой оптимизации). Я думаю, что рассмотрение примера проясняет проблемы, о которых я говорил, например ::1014*
#include <stdlib.h>
int do_stuff(); // returns true/false if things were changed
int other_stuff(); // returns true/false if changed
int main() {
int has_all_except = 1;
void *node = &has_all_except;
while (node != NULL && has_all_except) {
int changed = 0; // flag to watch for changes
nochanges: // Place to jump to to unconditionally
changed |= do_stuff();
changed |= other_stuff();
if (!changed)
goto nochanges; // Unconditional jump
}
}
Проблема в том, что нам удалось ввести безусловный переход, , но сам безусловный переход применяется условно и , что условие не проще, чем первая часть &&
сама.
Это означает:
- Один дополнительный
int
в качестве "флага", чтобы увидеть, что что-то изменилось
- Сотрудничество с
do_stuff()
и other_stuff()
- если что-либо не является кооперативным, то это невозможно (и маловероятно, что ваш компилятор сможет выяснить это для вас через модули trhanslation)
- Чем больше кода, тем меньше места в кэше вашего процессора
- Чем больше веток, тем больше возможностей для остановок конвейера, прогнозирования и худших прогнозов
Если это стоит сделать и безопасно сделать, то я вполне уверен, что это будет сделано соответствующим современным компилятором. Если это не сделано, то я подозреваю, что оно того не стоит (без лучшей производительности) или небезопасно применять. В любом случае компилятор, скорее всего, понимает тонкости оптимизации циклов для вашего кода на вашей конкретной платформе гораздо лучше, чем подавляющее большинство программистов!