Сначала давайте предположим, что «p» является типом указателя.
В противном случае все операции являются просто синтаксическим сахаром для вызовов функций.
Позволяет нам разбить утверждение на части.
int* p = a;
*p++ = *p + 32;
<< Sequence Point >>
// Part 1: p++
// Note the definition of post increment in the standard is (5.2.6)
// The result of the expression p++ is the value of 'p' while the value of the
// objects represented by 'p' is incremented. This can be represented in pseudo code as:
(A) int* p1 = p;
(B) p = p + 1;
// Part 2: *p (On the result of Part 1) (On *p++)
(C) int& p2 = *p1; // Note the use of p1;
// Part 3: *p (On *p + 32)
// Note: There is no linkage between this use of 'p' and the 'p' in Part 1&2
(D) int& p3 = *p;
// Part 4: *p + 32;
(E) int p5 = p3 + 32; // Note the use of p3;
// Part 5: Assignment.
(F) p2 = p5;
<< Sequence Point >>
Ordering that must be preserved:
(A) Before (B)
(A) Before (C)
(D) Before (E)
(C) Before (F)
(E) Before (F)
Учитывая вышеуказанные ограничения:
Компилятор может переупорядочить эти инструкции несколькими способами,
Но главное, на что следует обратить внимание, это то, что (B) может произойти где угодно, единственное ограничение на (B) состоит в том, что это происходит после (A). Таким образом, значение p3, как определено в (D), может быть одним из двух различных значений в зависимости от точное положение (B).
Поскольку значение p3 не может быть определено здесь.
Полученный оператор имеет неопределенное поведение.