프로그래밍임베디드 개발자, 백엔드 개발자

C 언어에서 조건 연산자(삼항 연산자)의 작동 방식과 구조를 설명하십시오. 이를 사용할 때 발생할 수 있는 형 변환 및 부작용과 관련된 함정은 무엇입니까?

Hintsage AI 어시스턴트로 면접 통과

답변

삼항 조건 연산자(?:)는 조건에 따라 두 표현식 중 하나를 계산하고 반환할 수 있게 해줍니다:

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). 리팩토링 중에 숨겨진 오류가 발생했습니다: 두 표현식 모두 함수가 호출되었고(각자의 부작용을 가진 채), 오직 하나만 수행될 것으로 예상했으나 중첩된 매크로의 혼란으로 값이 두 번 수정되는 문제가 발생했고, 이는 상세한 테스트 과정에서만 발견되었습니다.