▼ 표 5-7 16비트 부호 없는 정수 타입을 음수로 만드는 과정
연산 |
십진수 값 |
b15 … b0 |
A |
240 |
0000000011110000 |
~A |
65295 |
1111111100001111 |
+1 |
65295 |
0000000000000001 |
-A |
65296 |
1111111100010000 |
이렇게 하면 부호 있는 정수 타입 산술식도 다소 깔끔하게 처리할 수 있다. 하지만 부호 있는 산술식에서 오버플로 발생 여부를 예측하기 어려워질 가능성이 있다. 부호 없는 값이라면 원점으로 되돌아갈 상황에 대해 부호 있는 타입은 오버플로 동작이 정의되어 있지 않기(비정의(undefined) 동작이기) 때문이다. 예를 들어 동일한 동작을 수행하는 두 루프를 살펴보자.
for (unsigned i = 1; i; ++i) do_something(); for ( signed i = 1; i; ++i) do_something();
첫 번째 루프에서 값이 변하는 과정은 쉽게 예측할 수 있다. 카운터 i는 UINT_MAX까지 증가하다가 0으로 되돌아간다. UINT_MAX-1번째를 실행한 뒤에 i가 다시 0으로 돌아가기 때문에 시간은 좀 걸리겠지만 루프는 결국 멈춘다.
두 번째 루프도 비슷하게 실행되지만 부호 있는 타입에 대한 오버플로 동작이 정의되어 있지 않기 때문에 컴파일러는 이 부분을 완전히 무시할 가능성이 있다. 게다가 양수 값에서 시작했으므로 프로그램에 정의된 동작이 존재하는 한 i는 절대 음수나 0이 되지 않는다고 간주할 수 있다.