Есть много причин не требовать, чтобы одна из сторон была оценена раньше другой. Более интересным вопросом является необходимость оценки обеих сторон в сочетании с побочными эффектами, прежде чем сам оператор присваивания что-либо предпримет. Я бы предположил, что такое требование ослабит некоторые ограничения псевдонимов, но в некоторых случаях потребует больше работы для компилятора. Например, предположим, что «foo» и «bar» являются указателями на большие структуры, адреса которых будут перекрываться. Утверждение "* foo = * bar;" будет представлять неопределенное поведение в соответствии с текущим стандартом. Если бы между оценкой операндов и присваиванием была точка последовательности, такое утверждение гарантированно сработало бы. Такая гарантия потребовала бы более сложного для оператора присваивания, требующего большего и более медленного кода, даже если на практике указатели никогда не будут перекрываться.
Пример:
unsigned char foo[100];
typedef struct {int x, int y;} POINT;
POINT *p1 = (POINT*)foo;
POINT *p2 = (POINT*)(&(p1->y));
Учитывая вышеприведенные декларации, я думаю, что следующие утверждения имеют строго определенное поведение и не включают никакого неопределенного поведения.
p1->y = somevalue; // Sets p2->x to somevalue
p2->x = somevalue; // Sets p1->y to somevalue
*p1 = mystruct; // Sets p2->x to mystruct.y
*p2 = mystruct; // Sets p1->x to mystruct.x
Следующие два утверждения, однако, будут включать неопределенное поведение:
*p1 = *p2;
*p2 = *p1;
Если бы в знаке равенства была точка последовательности, компилятору пришлось бы либо сравнивать p1 и p2, либо копировать исходный операнд во временное местоположение, а затем копировать его в место назначения. Стандарт, однако, ясно дает понять, что оба вышеуказанных утверждения считаются неопределенным поведением. Стандарт требует, чтобы компиляторы генерировали код, который работает правильно при копировании структуры в неперекрывающуюся структуру, но не накладывает никаких ограничений на то, что могут делать компиляторы, если структуры перекрываются. Компилятор, который превращает процессор в цикл, отправляющий "Frink Rules!" при этом каждый открытый TCP-сокет не будет нарушать стандарт.