Тернарный условный оператор (?:) позволяет вычислять и возвращать одно из двух выражений в зависимости от условия:
result = cond ? expr_true : expr_false;
int a = 10, b = 0; int max = (a > b) ? a : b; // max = 10
"Если два выражения тернарного оператора возвращают объекты разного типа (например, указатель и ноль), каков будет тип результата?"
Многие утверждают, что компилятор всегда "угадывает" тип результата. На самом деле, если одно из выражений — указатель, а другое — 0 или NULL, то результат будет иметь тип указателя. Если же разница более сложная — например, возвращается указатель разного типа или тип int и тип enum — возможна неочевидная потеря информации, а иногда компилятор выдаёт ошибку.
struct node *p = NULL; void *v = cond ? p : NULL; // ok void *z = cond ? p : 0; // ok int i = cond ? 0 : "abc"; // ошибка: несовместимые типы
История
В крупном проекте с кросс-компиляцией используемый выражение
cond ? ptr : 0возвращало указатель при одном компиляторе и int при другом (где 0 интерпретировался строго как int). Система падала при попытке использовать результат как указатель.
История
В финансовом пакете, где функции возврата использовали тернарный оператор с "голыми" литералами (
cond ? 0.0 : 1), тип результата по неосторожности стал double, хотя ожидался int, из-за чего возникли ошибки сравнения и печати.
История
В одной из библиотек производился вызов с выражением побочного эффекта:
flag ? inc(x) : dec(x). При рефакторинге скрытая ошибка: оба выражения вызывали функцию (со своими side-effects), хотя ожидалось, что выполнится только одно. Путаница с вложенными макросами привела к двойному изменению значения, что обнаружили только в процессе детального тестирования.