А я про то, что к этой правильности
evaluated only once не имеет отношения :-)
Код
volatile unsigned char vc;
unsigned char v;
void foo1()
{
if (++vc == 0) v = 0; // тут для vc работает evaluated only once
}
void foo2()
{
if ( (vc = vc + 1) == 0) v = 0; // тут для vc НЕ работает evaluated only once
}
Функции foo1() и foo2() компилируются одинаково разными версиями компиляторов.
4.5.3 в
обеих функциях
делает дополнительное считывание vc для проверки на 0
4.7.0 в
обеих функциях
не делает дополнительное считывание vc для проверки на 0
evaluated only once имеет отношение к тому примеру, который привел я. С ним наоборот —
в foo1() определение адреса элемента массива для инкремента делается один раз
обеими комипляторамив foo2() определение адресов элементов массива делается два раза обеими компиляторами, один раз для считывания, один раз для записи (у 4.7.0 немного эффективнее код, но логика та же — два раза подряд зачитывается vc, вычисляется два адреса в X и Z, потом
ld reg, X $ inc reg $ st Z, reg ).
К обсуждаемой оптимизации имеет отношение другое место, то ж самое, которое относится к
Код
volatile unsigned char vc;
unsigned char v;
v = vc = 0; // Напрямую писать 0 в v , а не считывать vc
А именно:
Цитата(ISO/IEC 9899 @ Dec 01 1999)
6.5.16 Assignment operators
…
3 An assignment operator stores a value in the object designated by the left operand. An assignment expression has the value of the left operand after the assignment, but is not an lvalue. An assignment expression has the value of the left operand after the assignment, but is not an lvalue. The type of an assignment expression is the type of the left operand unless the left operand has qualified type, in which case it is the unqualified version of the type of the left operand.
Т.е.
++vc, равно как и
vc = vc + 1 имеют значение vc + 1 но имеет тип просто
unsigned char. И вообще — не является lvalue, не есть объектом, cуществующим где-то, кроме временных ячеек абстрактной машины.
p.s[0] т.е., выходит даже, что это багфикс, а не улучшение оптимизатора ???
Что предыдущие компиляторы ни в коем случае не должны были зачитывать, так как это не требуется стандартом (и фактически отвергается -- «is not an lvalue», результат выражения равен значению правой части, приведенной к неквалифицированному типу левой, существует только как результат, но не как объект), но может породить (неучитываемый и неизвестный) побочный эффект?
p.s[1]
Сергей Борщ: я так и не прочёл толком те линки, которые тогда по быстрячку нагуглил и тебе в джаббер кинул

. Но, кажется, они об этом