#cpp #c #алгоритм
На просторах сети нашел несколько "странное" применение конструкций языка. Вот небольшой пример, который я набросал сам, просто по "шаблону": #includeusing namespace std; void foo(const int i) { cout << "foo(" << i <<")" << endl; } int main() { int c = 10; switch(c&3) while((c-=4)>=0) { foo(c); case 3: foo(c); case 2: foo(c); case 1: foo(c); case 0:; } return 0; } Специально для незнающих не раскрываю "мелочи", пусть будет интригой) От "знающих" прошу чисто практический пример - и с объяснениями мелочей. Почему сия конструкция иногда (или часто?) дает профит.
Ответы
Ответ 1
Это по сути ручная размотка цикла, известная как Duff's device. Сейчас она практически не нужна, так как современные компиляторы делают это сами, если считают нужным. (А «считать нужным» они умеют намного лучше нас.) Для старых компиляторов имело смысл, т. к. позволяло сэкономить на управлении циклом, выполняя по нескольку итераций (в вашем случае — 4) за раз. Странный код с switch нужен, понятно, для того, чтобы правильно работал случай, когда длина цикла не кратна размеру размотки.Ответ 2
Почему сия конструкция иногда (или часто?) дает профит. Данная конструкция "дает профит" потому, что уменьшает количество условных переходов в программе по сравнению с тривиальной реализацией того же цикла for (int c = 10; c > 0; --c) foo(); Подразумевается, что тривиальная реализация будет странслирована в машинный код "один-в-один", т.е. будет проверять условие продолжения цикла после каждой из 10 итераций. Толковая "развернутая по четыре" реализация проверяет условие продолжения своего цикла только 3 раза (10 / 4 с округлением вверх). Надо заметить, что у вас получилась слегка "некачественная" реализация Duff's Device, которая иногда делает на одну проверку больше, чем классическая реализация. Например для случая c = 4 ваш код сделает две проверки условия цикла, в то время как классическое Duff's Device - только одну. (Умиляет также "пионерская оптимизация" с заменой % 4 на & 3.)
Комментариев нет:
Отправить комментарий