2008년 03월 27일
C++ 에서 UINT 와 int 계산규칙은 도대체 어떻게 되였는가?
C++ 에서 -10 / (UINT)5 = 858993457, (UINT)10 / (-5) = 0 이다!
UINT m = 10;
UINT n = 5;
int s = -(int)m / n;
하면 s = 858993457
int s = m / (-(int)n);
하면 s = 0 이 된다.
이렇게 안하고도 그냥 watch 창에 -10 / (UINT)5 , (UINT)10 / (-5) 하고 넣으면
858993457 과 0 이 나온다.
이것때문에 꼬박 33분33초를 고민했다.
ps: 왜 이렇게 되는지 알려주시면 감사하겠습니다.
UINT m = 10;
UINT n = 5;
int s = -(int)m / n;
하면 s = 858993457
int s = m / (-(int)n);
하면 s = 0 이 된다.
이렇게 안하고도 그냥 watch 창에 -10 / (UINT)5 , (UINT)10 / (-5) 하고 넣으면
858993457 과 0 이 나온다.
이것때문에 꼬박 33분33초를 고민했다.
ps: 왜 이렇게 되는지 알려주시면 감사하겠습니다.
# by | 2008/03/27 20:17 | 컴퓨터 | 트랙백 | 덧글(4)





☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
제 기억이 맞다면 unsigned 값과 signed 값이 연산될때는
묵시적으로 unsigned로 자동 형변환이 되는걸로 알고 있습니다.
첫번째의 경우 -10은 사실 unsinged로는 5보다 굉장히 큰값입니다
-10은 0xFFFFFFFF6 이고 5는 0x00000005 일 뿐이죠.
그래서 아마 저런 결과가 나왔을겁니다
두번째의 경우도 마찬가지죠
10, 즉 0x0000000A 를 -5, 즉 0xFFFFFFFA로 나누었으니 1 이하가 나왔을거고
저장된 자료형이 int니까 소수점은 버려져서 0이 결과가 되을겁니다.
그러니까 핵심은 unsigned와 signed가 만나서 계산하는 과정에서는
unsigned로 자동 형변환 되서 계산이 된다는 겁니다
그런 뒤에 int s에 저장될때는 또 다시 signed로 형변환이 되서 저장되겠죠.
도움이 되셨기를.
그런데 / 연산에서만 이런 현상이 나타나고 +, -, * 에서는 제대로 결과가 나옵니다.
정확한 연산규칙을 알아야 할텐데요....
계산은 전부 unsigned로 여기고 연산한다음에 int에 저장되므로 결과를 signed로 읽어보면됩니다.
일단 + 계산부터
[-10]0xFFFFFFFF6 + [5]0x00000005 = 0xFFFFFFFB 이놈은 signed로 -5가 맞습니다
[10]0x0000000A + [-5]0xFFFFFFFB = 0x100000005 이 되는데 최상위 값은 오버플로우로 잘리고 5가 됩니다
다음 - 계산
[-10]0xFFFFFFFF6 - [5]0x00000005 = 0xFFFFFFF1 이놈은 signed로 -15 맞습니다.
[10]0x0000000A - [-5]0xFFFFFFFB = 0xFFFFFFFF0000000F 이지만 오버플로우 짤리면 15 맞습니다.
다음 * 계산
[-10]0xFFFFFFFF6 * [5]0x00000005 = 0x4FFFFFFCE 마찬가지로 오버플로우 제거하면 -50입니다
[10]0x0000000A * [-5]0xFFFFFFFB = 0x9FFFFFFCE 마찬가지로 오버플로우 제거하면 -50입니나
마지막 / 계산
[-10]0xFFFFFFFF6 / [5]0x00000005 = 0x33333331 이렇게 나오는데요
10진수로 변환하면 858993457 입니다 물론 최상위 비트는 0이므로 양수고요
[10]0x0000000A / [-5]0xFFFFFFFB = 0x0
이건 뭐 당연한 결과죠 소수 표현은 불가능 하므로 0입니다
c계열 언어들은 대부분 형이 다른 연산에서 좀더 넓은 형으로 변환되어 연산되는 경향이 있습니다
unsigned와 signed도 그런 의미로 해석하면 쉬울거 같습니다.
그러니 signed 와 unsigned 의 연산에서 unsigned 로 변환하여 처리한다는 말씀이시군요.