J>Мне вот интересно, а что должно получится в результате следующего выражения в переменной j:
int i=1;
int j;
j=(++i)*2+ --i;
Это известный пример так называемого неопределенного поведения, что является одной из худших ошибок программирования, т.к. в отличие от других она может "прикидываться" вполне законной конструкцией. В данном случае сказываются следующие моменты:
1) в общем модификация и запись в ячейку памяти не является атомарной операцией (на некоторых системах компилятору, например, требуется загрузить значение в регистр, инкрементировать его, после чего записать его обратно);
2) стандарт не требует от компилятора генерации "постоянной" записи промежуточных значений (подобно тому как кэшируются операции с диском);
3) попытка одновременной записи в одну ячейку может закончиться очень и очень плохо: от изменяющегося от компилятора к компилятору (самый вероятный сценарий), от билда к билду (тоже бывает), или даже от запуска к запуску значения выражения до нестабильной работы системы и/или core dump в зависимости от самых различных факторов;
4) хорошей новостью является то, что в C++ определены так называемые точки следования (sequence points), в которых гарантируется, что любые операции записи таки совершились, например, точками следования сопровождаются вызовы функций, операции ||, && и т.д.;
5) в общем случае одну и ту же переменную между двумя точками следования безопасно можно модифицировать только один раз;
6) так вот, в приведенном выражении между двумя модификациями i нет точки следования, что приводит к неопределенному поведению, иначе говоря, компилятор волен творить любые фокусы, как иногда шутят, даже генерировать код для форматирования диска.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен