Qual é o resultado de + = em C e C ++?

Eu tenho o seguinte código:

#include  int main(int argc, char **argv) { int i = 0; (i+=10)+=10; printf("i = %d\n", i); return 0; } 

Se eu tentar compilá-lo como uma fonte C usando o gcc, recebo um erro:

 error: lvalue required as left operand of assignment 

Mas se eu compilar como uma fonte C ++ usando g + + eu não recebo nenhum erro e quando eu executar o executável:

 i = 20 

Por que o comportamento diferente?

A semântica dos operadores de atribuição de compostos é diferente em C e C ++:

Norma C99, 6.5.16, parte 3:

Um operador de atribuição armazena um valor no object designado pelo operando esquerdo. Uma expressão de atribuição tem o valor do operando esquerdo após a atribuição, mas não é um lvalue.

Em C ++ 5.17.1:

O operador de atribuição (=) e os operadores de atribuição compostos, todos agrupam da direita para a esquerda. Todos exigem um lvalue modificável como o operando esquerdo e retornam um lvalue com o tipo e valor do operando esquerdo após a atribuição ter ocorrido.

EDIT: O comportamento de (i+=10)+=10 em C ++ é indefinido em C ++ 98, mas bem definido em C ++ 11. Veja esta resposta à pergunta da NPE para as partes relevantes das normas.

Além de ser um código C inválido, a linha

 (i+=10)+=10; 

resultaria em um comportamento indefinido em C e C ++ 03, pois modificaria i duas vezes entre os pontos da sequência.

Por que é permitido compilar em C ++:

[C ++ N3242 5.17.1] O operador de atribuição (=) e os operadores de atribuição compostos todo o grupo da direita para a esquerda. Todos exigem um lvalue modificável como seu operando esquerdo e retornam um lvalue referente ao operando esquerdo.

O mesmo parágrafo continua dizendo que

Em todos os casos, a atribuição é sequenciada após o cálculo do valor dos operandos direito e esquerdo, e antes do cálculo do valor da expressão de atribuição.

Isso sugere que, em C ++ 11, a expressão não tem mais um comportamento indefinido.