Здравствуйте Vi2, Вы писали:
Vi2>Но теперь вот какой вопрос по следующему коду.
Vi2>Vi2> int z = 1;
Vi2> int z2 = z + ++z + ++z;
Vi2> z = 1;
Vi2> int z3 = ++z + z + ++z;
Vi2> z = 1;
Vi2> int z4 = ++z + ++z + z;
Vi2> sprintf(szDbgBuf,"%d %d %d\n",z2,z3,z4);
Vi2> OutputDebugString(szDbgBuf);
Vi2>Результат: 7 7 9 (MS VC60)
Vi2>
Vi2>Имеет ли право компилятор подставлять значение z (там, где оно является операндом, я его выделил) отличное от того, которое оно имело ДО начала вычисления выражения, стоящее за знаком "=" ?
Да, имеет. Он имеет право сделать вообще все, что угодно. Эти выражения страдают от той же самой проблемы, которая имеет место в твоем исходном примере. Переменная 'z' скалярного типа модифицируется между парой соседних точек следования более одного раза. Это выражение порождает неопределенное поведение. Компилятор имеет правло сгенерировать код, в результате выполнения котрого программа просто рухнет.
Vi2>Насколько я помню по теории алгоритмов выражение переводит одно состояние в другое, причем предыдущее состояние не меняется и определяет следующее. Поэтому, кажется, каждый из ++ определяет какие-то дополнительные состояния. Т.е. мне не совсем понятна роль этих дополнительных состояний.
Во-первых, в С++ разделителями состояний являются не выражения, а точки следования. Во многих случаях (в большинстве случаев) расположение точек следования совпадает с границами выражений. Но может и не совпадать.
Во-вторых, между двумя точками следования нет никаких дополнительных состояний. Они запрещены стандартом языка. Компилятор не занимается проверкой этого запрещения, они запрещены именно декларативно. Т.е. стандарт языка запрещает прграммисту писать код, который порождает такие промежуточные состояния. Если программист пишет такой код, то за последствия отвечает он сам.
В стандарте языка сказано, что
a) между парой соседних точек следования переменная скаларного типа может быть модифицирована не более одного раза и
b) если такая переменная модифицируется, то читать ее старое значение разрешается только для того, чтобы вычислить ее новое значение.
Твой код порождает неопределенное поведение согласно первой половине этого правила. Вот такой код
int z = 1;
int z2 = z + ++z;
тоже порождает неопределенное поведение, согласно второй половине этого правила.
Рассуждать о каких-то промежуточных состояниях по отношению к этому коду нет никакого смысла, потому что совершенно невозможно определить, что этот код означает. Этот код просто-напросто некорректен.