Operator warunkowy ternarny (?:) pozwala na obliczenie i zwrócenie jednego z dwóch wyrażeń w zależności od warunku:
result = cond ? expr_true : expr_false;
int a = 10, b = 0; int max = (a > b) ? a : b; // max = 10
"Jeśli dwa wyrażenia operatora ternarnego zwracają obiekty różnych typów (na przykład wskaźnik i zero), jaki będzie typ wyniku?"
Wielu twierdzi, że kompilator zawsze "zgaduje" typ wyniku. W rzeczywistości, jeśli jedno z wyrażeń to wskaźnik, a drugie to 0 lub NULL, to wynik będzie miał typ wskaźnika. Jeśli różnica jest bardziej skomplikowana – na przykład, zwracany jest wskaźnik różnego typu lub typ int i typ enum – możliwa jest nieoczywista utrata informacji, a czasami kompilator zgłasza błąd.
struct node *p = NULL; void *v = cond ? p : NULL; // ok void *z = cond ? p : 0; // ok int i = cond ? 0 : "abc"; // błąd: niezgodne typy
Historia
W dużym projekcie z krzyżową kompilacją używane wyrażenie
cond ? ptr : 0zwracało wskaźnik przy jednym kompilatorze i int przy innym (gdzie 0 było interpretowane ściśle jako int). System zawieszał się podczas próby użycia wyniku jako wskaźnika.
Historia
W pakiecie finansowym, gdzie funkcje zwrotu używały operatora ternarnego z "nagimi" literami (
cond ? 0.0 : 1), typ wyniku nieostrożnie stał się double, podczas gdy oczekiwano int, co spowodowało błędy w porównaniach i wydrukach.
Historia
W jednej z bibliotek wywołano wyrażenie z efektem ubocznym:
flag ? inc(x) : dec(x). Podczas refaktoryzacji ukryty błąd: oba wyrażenia wywoływały funkcję (z własnymi efektami ubocznymi), podczas gdy oczekiwano, że zostanie wykonane tylko jedno. Zamieszanie z zagnieżdżonymi makrami prowadziło do podwójnej zmiany wartości, co wykryto dopiero w trakcie szczegółowego testowania.