Цитата(hd44780 @ May 4 2012, 11:39)

Вообще volatile "заставляет" компилятор не делать никаких предположений о значении переменных. Т.е. переменная всегда берётся из её места в памяти, даже если она осталась где-то в регистрах.
Не только «берется», но и «кладётся», если уж на то пошло.
Вообще-то компилятор может выбросить вообще весь код, если от этого не меняется observable behavior программы, извините мне моё обычное занудство с терминологией из стандартов С/С++, а не из надписей на заборах. Холостой цикл его не меняет, так как просто задержка не «замечается» компилятром. Есть еще задержки памяти разного рода, кешей и винчестера — откуда ему об этом всём знать?
Может, если переменная ляжет в регион внешнего ОЗУ меги64, к которому несколько тактов ожидания — цикл в разы удлиннится по сравнению с переменной во внутренней памяти, а тот в разы относительно переменной в регистре. Если ему обращать на это внимание, он вообще оптимизировать не сможет.
Если компилятор может выкинуть весь код кроме последнего оператора тут:
Код
float a, b, c;
int i;
...
i = (int)a;
i = b*sqrt(i*i + c*c) + 0.5f;
// может я знаю, что этот код выше выполняется гарантированно дольше, чем нужная мне задержка — какого беса он его убрал?
i = 0;
То почему ему нельзя выбросить пустой цикл — ничего не делающий реального?
Ещё
тут почитайте. Он не только выбросить ничего не делающий с его точки зрения код имеет право, но и переставлять местами делающий что-то полезное даже с его точки зрения.
Так вот volatile говорит компилятору, что он не может строить предположений о «видимости» работы с данной переменной снаружи независимо от её размещения в памяти, регистрах, ...
Даже если он работает с ней
только в памяти (например, pic16 просто не сильно-то и может держать переменные в регистрах и имеет команду декремента с пропуском прямо на памяти).
Цитата(hd44780 @ May 4 2012, 11:39)

Про _delay_ms(), _delay_us() тоже вставлю свои 5 копеек. У меня они НИКОГДА нормально не работали. Всегда хрен знает что с ними творится. Может тоже "отрыжки" оптимизации влияют - не знаю, не исследовал их.
Они всегда работали нормально (ну с учётом того, что не учитывали время в прерываниях, так этого никто и не обещал).
Просто всегда нужно было включать оптимизацию и им на вход подавать константы, а не переменные, так это вроде всегда было в документации описано.