Порядок оценки вложенных выражений

Стандарт C ++ 11 (5.17, expr.ass) утверждает, что

Во всех случаях присваивание последовательности после вычисления значения
правого и левого операндов, и до вычисления значения
выражение присваивания. По отношению к
неопределенно-последовательный вызов функции, операция соединения
задание является одной оценкой

Значит ли это, что выражение:

int a = 1, b = 10;
int c = (a+=1) + (b+=1);

if ( c == 10+1+1+1 ) {
printf("this is guaranteed");
} else {
printf("not guaranteed");
}

всегда буду оценивать c==23?

1

Решение

Это всегда гарантировано, и последовательность перед правилами
(или правила точки последовательности в пре-C ++ 11) не нужно
определить это. В C ++ каждое (под) выражение имеет два важных
эффекты в сгенерированном коде: оно имеет значение (если оно не
тип void), и это может иметь побочные эффекты. Последовательный
Правила точки до / последовательности влияют, когда побочные эффекты
гарантированно состоялось; они не влияют на стоимость
подвыражений. В вашем случае, например, значение
из (a += 1) это значение a будет после назначения,
независимо от того, когда фактическое назначение имеет место.

В C ++ 11 актуальная модификация a гарантированно взять
место до модификации c; в до C ++ 11 не было
гарантия относительно заказа. В этом случае, однако, есть
Соответствующая программа никак не могла увидеть эту разницу, поэтому
не имеет значения (Это будет иметь значение в таких случаях, как c = (c += 1),
что было бы неопределенным поведением в пре-C ++ 11.)

1

Другие решения

Выражение

int c = (a+=1) + (b+=1);

(редактировать: добавлены недостающие скобки, я думаю, это то, что вы хотели)

имеет следующие подвыражения

(1) a+=1
(2) b+=1
(3) (1)+(2)
(4) c = (3)

Порядок, в котором оцениваются (1) и (2), не указан, компилятор может выбирать любой порядок, который ему нравится.

Оба (1) и (2) должны быть оценены до Компилятор может оценить (3).

(3) должны быть оценены до Компилятор может оценить (4).

Теперь, когда порядок вычисления (1) и (2) не имеет значения, общий результат хорошо определен, ваш код всегда будет давать 13 и выведите «теперь это стандарт». Обратите внимание, что так было всегда, это не ново для C ++ 11.

2

В вашем примере компилятор выдаст ошибку, потому что приоритет оператора сложения выше, чем приоритет оператора присваивания. Таким образом, сначала будет вычислено 1 + b, а затем будет попытка присвоить 1 выражению (1 + b), но (1 + b) не является lvalue.

1
По вопросам рекламы [email protected]