L'opérateur conditionnel ternaire (?:) permet de calculer et de retourner l'une des deux expressions en fonction d'une condition :
result = cond ? expr_true : expr_false;
int a = 10, b = 0; int max = (a > b) ? a : b; // max = 10
"Si deux expressions de l'opérateur ternaire retournent des objets de types différents (par exemple, un pointeur et zéro), quel sera le type du résultat ?"
Beaucoup affirment que le compilateur "devine" toujours le type du résultat. En réalité, si l'une des expressions est un pointeur et l'autre est 0 ou NULL, le résultat aura le type du pointeur. Si la différence est plus complexe — par exemple, un pointeur d'un type différent ou un type int et un type enum — il peut y avoir une perte d'information non évidente, et parfois le compilateur renvoie une erreur.
struct node *p = NULL; void *v = cond ? p : NULL; // ok void *z = cond ? p : 0; // ok int i = cond ? 0 : "abc"; // erreur : types incompatibles
Histoire
Dans un grand projet de cross-compilation, l'expression utilisée
cond ? ptr : 0retournait un pointeur avec un compilateur et un int avec un autre (où 0 était interprété strictement comme un int). Le système plantait lors de l'utilisation du résultat comme pointeur.
Histoire
Dans un package financier, où les fonctions de retour utilisaient l'opérateur ternaire avec des littéraux " nus " (
cond ? 0.0 : 1), le type du résultat était devenu par inadvertance double, bien que l'on s'attendait à ce que ce soit un int, ce qui a conduit à des erreurs de comparaison et d impression.
Histoire
Dans l'une des bibliothèques, un appel était effectué avec une expression à effet secondaire :
flag ? inc(x) : dec(x). Lors du refactoring, une erreur cachée : les deux expressions appelaient une fonction (avec leurs effets secondaires), alors qu'on s'attendait à ce qu'une seule soit exécutée. La confusion avec les macros imbriquées a conduit à une modification double de la valeur, ce qui n'a été découvert qu'au cours de tests détaillés.