12.09.00
АвторИ опять я публикую здесь текст из конференции SU.C_CPP. Впору заводить для этого отдельный раздел ;) Автор этого письма, Александр Кротов, является человеком, который умеет цитировать стандарт языка C++. Это, кстати, очень сложно: ведь нужно помнить что и где находится, что бы при ответе на вопрос сразу же дать нужный пункт стандарта. Собственно, цитируемое ниже письмо, как мне кажется, может предоставлять некоторый интерес со стороны программистов на C++. Опять же, делаю автору (Александру) всевозможные реверансы и прошу всяческих прощений за использование его письма в своем разделе. Еще раз повторяю --- автор текста ниже не я, а Александр Кротов (давать его почтовый адрес не хочу, потому что на меня уже сыпется спам и, я уверен, на любой почтовый адрес упомянутый на страничке, он тоже будет сыпаться; интересующееся адресом Александра, могут спросить у меня). Письмо датировано 21 апрелем 1999 года. |
Hапример, в тех
случаях, когда x объявлен с модификатором volatile (насколько я понимаю,
volatile lvalue должен быть физически "взят" вне зависимости от того, с какой
стороны от знака операции присваивания он находится; первая запись в этом
случае просто не будет иметь определенного смысла, я думаю).
А вот пример мне не нравится. Обычно под побочными эффектами подразумевают нечто иное.
И насчет volatile тут ты тоже не совсем прав. Точное значение volatile
по стандарту зависит от компилятора, по этому есть смысл говорить только о
том, что компиляторы "как правило" делают с volatile переменными.
Hапример есть целый класс оптимизаций связанных с value numbering.
Оптимизации из этого класса позволяют, например, выделять общеие подвыражения
(local/global common subexpressions), выносить из цикла инвариантные
вычисления, а то и совмещать эти две приятные процедуры (partial redundancy
elimination, например популярный сейча lazy code motion aka LCM).
Для всех этих оптимизаций уже придуманы хорошие формальные модели, которые,
в свою очередь, уже много где описаны ;-) Так что есть смысл ожидать того,
что в том компиляторе, которым ты пользуешься они хотя-бы частично
реализованы.
Так вот, к чему я это все. Как правило volatile отражается именно на
таких оптимизациях. (В формализмах учесть этот самый volatile
очень легко).
В твоем примере
volatile int x; x = x^n;
или
x ^= n;
особой разницы нет. В первом случае значение x прочитано и тутже
перезаписано. Очень грубо чтение и запись можно считать атомарными.
Во втором случае имеем (столь же грубо) одну атомарную операцию.
Здесь то, что x - volatile на результате не может отразиться.
Примеры, где volatile может сыграть:
int a, b, c, d; ... c = x+a+b; ... // код не меняющий ни x, ни a d = x+a;
Здесь (x+a) - общее подвыражение, и если x - volatile, то компилятор
скорее всего не будет его оптимизировать.
Другой пример
while (x<5) {
// что-то не меняющее x
};
Здесь очевидно, что условие цикла, не будь x - volatile, не
меняется. То есть его можно соптимизировать вынеся лишние вычисления
из цикла
if (x<5)
while(1) {
// ....
}
Если же x - volatile компилятор скорее всего такой оптимизации делать
не будет.
| Бъерн Страуструп | Язык программирования C++, 3 издание. |