Ok. Vou te explicar a parte do “porque quiseram assim”.
Em Java, uma expressão como:
i = i++;
É interpretada da seguinte forma:
int valorAntigo = i;
i = i + 1;
i = valor antigo;
No C não existe uma definição clara do que isso pode fazer. Porém, na maior parte das implementações que conheço, isso será interpretado da seguinte forma:
i = i;
i++;
Ou seja, no C, graças a sua política minimalista, fazem o que chamamos de “delayed increment”.
Entretanto, em c ou c++, receber o valor de uma variável que foi pós incrementada na própria variável é considerado um estilo pobre de programação, até porque, isso em C é um “undefined behavior”, o que quer dizer que o padrão não cobre esse caso em específico.
Então, não seria estranho encontrar compiladores que geram resultados iguais ao do Java. Ou mesmo, descobrir um compilador que gera resultados diferentes usando políticas diferentes de otimização (mais raro, porém, nada se garante em undefined behaviors).
Isso explica porque esse código imprime 0 em Java, e 1 em C:
int i = 0;
i = i++;
System.out.println(i);
Como falei anteriormente, não existe uma especificação matemática para o operador de “pós incremento”. Como ele não é parte da matemática padrão sua implementação está sujeita ao gosto ou entendimento do criador da linguagem ou do compilador.
Por isso simplesmente olhar para a tabela de precedência não diz muita coisa.