프로그래밍C 시스템 프로그래머

C에서 부호가 다른 숫자(signed/unsigned) 사이의 형 변환의 특징을 설명하고, 발생할 수 있는 문제점, signed/unsigned 유형의 산술 및 비교 연산에서 예기치 않은 결과를 피하는 방법, 그리고 이것이 프로그램의 이식성에 미치는 영향은 무엇인가요?

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

답변

C에서 자동 형 변환은 "일반 산술 변환" 원칙에 따라 작동합니다. 부호가 다른 숫자(signed/unsigned)가 표현식에 참여할 때 다음 규칙에 따라 변환이 발생합니다:

  • 하나의 피연산자가 unsigned이고 다른 하나가 signed인 경우, signed가 자동으로 unsigned로 변환됩니다.
  • 이는 특히 비교 또는 산술 연산 시 예상치 못한 오버플로우를 초래할 수 있습니다.
  • 유형의 크기도 영향을 미칩니다: unsigned가 더 큰 비트 수인 경우 signed가 unsigned로 변환됩니다.

위험한 산술의 예:

int a = -1; // signed unsigned int b = 1; printf("%d\n", a < b); // 항상 false, a가 매우 큰 unsigned로 변환되기 때문

결과: -1이 unsigned로 변환되면 매우 큰 양의 정수가 됩니다.

기억해야 할 중요한 점:

  • 부호에 혼란이 올 수 있는 경우 항상 명시적으로 형 변환을 수행하십시오.
  • 유형의 크기(int, long, uint32_t 등)를 주의 깊게 살펴 변환이 예측 가능하게 이루어지도록 하십시오.
  • 특히 경계 검사 및 산술에서 signed 및 unsigned 변수 간의 논리를 분리하십시오.

함정 질문

질문: 표현식 (int)(unsigned)-1은 어떤 결과를 반환할까요?

예상치 못한 잘못된 답변: "-1, 왜냐하면 -1을 int로 변환하기 때문입니다."

올바른 답변: 표현식 (unsigned)-1에서 먼저 -1이 unsigned로 변환됩니다(32비트 플랫폼에서는 0xFFFFFFFF가 됨), 그 다음 다시 signed int로 변환됩니다. 이는 구현에 따라 다르지만, 대부분의 경우 다시 -1이 됩니다(2의 보수를 사용할 경우). 그러나 더 정확히 말하면: 결과는 signed 숫자의 표현 표준에 따라 달라지지만, 대부분의 구현에서는 -1이 될 것입니다.

예:

int x = (int)(unsigned)-1; // x == -1 대부분의 플랫폼에서

이 주제의 미미한 차이로 인한 실제 오류 예


이야기

문자열 처리기에서 크기 비교 함수를 사용했는데, 문자열 길이가 음수일 수 있는 경우 프로그램에서 오류를 알리지 않았습니다. 그러나 길이는 size_t(unsigned) 유형이었고, if(length < 0) 코드의 비교는 항상 false를 반환하여 무한 루프와 메모리 오버플로를 초래했습니다.


이야기

프로토콜 파싱 시 네트워크 패킷이 unsigned 필드를 포함했으나 로컬 변수는 signed였습니다. 일부 값을 처리할 때 unsigned 오버플로로 인해 패킷 길이 계산이 잘못되어 버퍼 오버플로 취약점이 발생했습니다.


이야기

로그의 날짜 비교 모듈에서 날짜를 unsigned int로 저장했으나 int로 날짜 범위를 검색했습니다. 특정 경계 값에서는 예상했던 예외가 발생하는 대신 잘못된 필터링 결과로 인해 중요한 로그가 손실되었습니다.