De fait, la seule garantie est celle indiquée par la norme. Tout autre code donnera un résultat indéfini (entendre par là qu'il donnera bien un résultat, mais qui peut changer selon le compilateur et la version, et que ce résultat peut potentiellement être de planter, de formater ton disque dur ou de transformer ton pc en cafetière).
Pollux (./26) :
Ben non, les deux sont du code invalide (enfin, invalide seulement s'il est exécuté, bien sûr), autrement dit non seulement le résultat n'est pas défini mais en plus ça peut très bien planter ^^
Je suis curieux de connaître ta source, parce que je vois nulle part indiqué que c'est invalide. Il est possible que ce soit un oubli, parce que pour l'opérateur d'assignation c'est bien spécifié que c'est non défini. En revanche pour l'opérateur de postincrémentation il n'y a pas de telle remarque.
[3 minutes plus tard]
Ah voilà c'est bon j'ai trouvé : "Between the previous and next sequence point an object shall have its stored value
modified at most once by the evaluation of an expression.".
C'était dans la définition même d'une expression, et pas du côté des assignations

Du coup, x++ + x++ est bien illégal.
En revanche, putc(x++) || putc(x++) est légal et incrémente x une fois avant l'appel au premier putc, et une fois entre le || et l'appel au second putc.