Lorsque vous utilisez {3,2,4}, vous utilisez l'initialisation scalaire, mais vous fournissez plus d'éléments que vous ne le devriez. Cela déclenchera un avertissement du compilateur, mais il compilera et exécutera, et le premier élément de l'initialisation scalaire sera attribué à la variable i.
Lorsque vous utilisez (3,2,4), vous utilisez en fait l'opérateur virgule (les parenthèses sont nécessaires parce que vous initialisez la variable). L'opérateur virgule évalue le premier opérande et rejette le résultat, puis évalue le second opérande et renvoie le résultat. Ici, vous évaluez donc 3, vous le rejetez, puis vous évaluez 2, vous le renvoyez (cette valeur de retour est utilisée comme opérande gauche de la deuxième virgule) et enfin vous évaluez 4, et vous le renvoyez, de sorte que le 4 est attribué à la variable i.
Voici une autre opération intéressante :
int i;
i = 3,4;
printf("%d\n",i);
Cela imprimera 3, car i=3 sera d'abord évalué (puisqu'il s'agit de l'opérande gauche de la virgule), et son résultat sera écarté. Ensuite, 4 sera évalué et son résultat sera retourné, mais ne sera pas attribué à la variable.
Et pour rendre les choses plus intéressantes :
int i,j;
j = (i = 3,4);
printf("%d %d\n",i,j);
Il en résultera l'impression de "3 4". En d'autres termes, tout ce que j'ai décrit ci-dessus se produira, mais lorsque le 4 sera évalué et renvoyé, il sera attribué à j.