Proven C BookEnglish GitHub

부록 C — 암묵 변환 요약

29장의 규칙을 표로 압축한 것이다.

정수 승격

bool, char, signed char, unsigned char, short, unsigned short, 비트 필드가 산술에 참여하면:

산술은 int보다 좁은 타입 위에서 일어나지 않는다.

통상 산술 변환 (두 피연산자의 공통 타입)

  1. 한쪽이 long double → 둘 다 long double
  2. 아니고 한쪽이 double → 둘 다 double
  3. 아니고 한쪽이 float → 둘 다 float
  4. 둘 다 정수 → 각각 정수 승격 후:

    • 부호가 같으면 → 더 넓은 쪽
    • 부호 없는 쪽이 더 넓거나 같으면 → 부호 없는 쪽
    • 부호 있는 쪽이 더 넓고 상대 값을 다 담으면 → 부호 있는 쪽
    • 그 밖 → 부호 있는 쪽의 부호 없는 판

실무 요약: 섞이면 넓은 쪽으로, 폭이 같으면 부호 없는 쪽이 이긴다. 부호 섞인 비교는 피한다(경고를 켜 두면 컴파일러가 짚어 준다).

가변 인자의 기본 진급

원형에 타입이 없는 자리(...)로 넘어가는 인자:

그래서 printf에 float 전용 서식이 없고, %f가 double을 받는다 (19·25·58장).

정수 변환 등급 (변환 규칙의 기준자)

통상 산술 변환이 “더 넓은 쪽”을 고를 때 쓰는 순서다. 위가 높다.

long long  >  long  >  int  >  short  >  char / signed char / unsigned char  >  bool

세 가지를 구별해 두어야 한다.

char·signed char·unsigned char는 서로 등급이 같다. 셋은 폭이 같으므로 하나의 칸에 든다.

bool의 등급은 그보다 낮다. 표준이 bool을 모든 부호 있는 정수 타입보다 낮은 등급으로 못박았다.

③ 등급은 폭이 아니다. 같은 폭이면 부호 없는 쪽과 부호 있는 쪽의 등급은 같고, 그때 통상 산술 변환에서 부호 없는 쪽이 이긴다. 그래서 -1 < 1u가 거짓이 된다 — -1이 거대한 부호 없는 값으로 바뀌기 때문이다(29장). 폭이 같아도 등급이 다를 수 있고(구현이 확장 정수 타입을 두는 경우), 등급이 같아도 부호가 결과를 가른다.

어떤 변환이 어떤 위험을 부르는가

변환일어나는 일위험
부호 있는 → 부호 없는2의 보수 값이 그대로 재해석된다음수가 거대한 값이 된다
부호 없는 → 부호 있는담기면 그대로, 아니면 구현 정의경계에서 값이 바뀐다
넓은 정수 → 좁은 부호 없는 정수2𝑁 로 나눈 나머지(정의됨)조용한 값 손실
넓은 정수 → 좁은 부호 있는 정수들어가면 그대로, 아니면 구현 정의C23 에서도 그렇다
정수 → 실수가까운 값으로 반올림큰 정수에서 정밀도 손실(8장)
실수 → 정수소수부를 버린다(0 방향)범위 밖이면 계약 밖
doublefloat정밀도를 줄인다반올림 오차
포인터 → void *무손실타입 정보만 잃는다
void * → 다른 포인터무손실정렬이 맞지 않으면 계약 밖(37장)
정수 → 포인터구현 정의출처(provenance)를 잃는다(14장)

표 98.1

조용한 변환이 일어나는 자리 목록

암묵 변환은 다음 자리에서 묻지 않고 일어난다.

그 밖의 자주 만나는 변환