Rambler's Top100 Service Этот текст распечатан с домашней странички Андрея Калинина (www.kalinin.ru).
Оригинал статьи находится по этому адресу: http://www.kalinin.ru/programming/cpp/12_09_00.shtml


volatile

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 издание.

©2000-2001 by Andrey L. Kalinin,
andrey@kalinin.ru