삼항 조건 연산자(?:)는 조건에 따라 두 표현식 중 하나를 계산하고 반환할 수 있게 해줍니다:
result = cond ? expr_true : expr_false;
int a = 10, b = 0; int max = (a > b) ? a : b; // max = 10
"삼항 연산자의 두 표현식이 서로 다른 타입의 객체를 반환하면(예: 포인터와 0) 결과의 타입은 무엇입니까?"
많은 사람들이 컴파일러가 항상 결과의 타입을 "추측"한다고 주장합니다. 실제로, 만약 하나의 표현식이 포인터이고 다른 하나가 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). 리팩토링 중에 숨겨진 오류가 발생했습니다: 두 표현식 모두 함수가 호출되었고(각자의 부작용을 가진 채), 오직 하나만 수행될 것으로 예상했으나 중첩된 매크로의 혼란으로 값이 두 번 수정되는 문제가 발생했고, 이는 상세한 테스트 과정에서만 발견되었습니다.