php와 unsigned int

@codemaru · July 14, 2009 · 3 min read

예전에 한 땐 phper였고, phpschool을 제 집 드나들듯 했던 시절이 있었습니다. 여튼 나름 php는 왠만큼은 다룬다고 생각하고 살았습니다. 그런데, 그런데,… php를 알게 된지 근 10년이 다 된 오늘에서야 php가 무부호 정수 unsigned int를 지원하지 않는다는 사실을 알았습니다. 이건 뭥미… ㅠㅠ

예전부터 이상하게 로그를 받는 php 페이지에서 특정 로그 코드만 올라오지 않는 현상이 있었습니다. 0xe??????? 형태의 윈도우 오류 코드였습니다. 그 로그 코드는 너무 밑에서부터 위쪽 까지 여행을 하던 놈인데다, 특별히 중요한 코드도 아니어서 그냥 그간 무시하고 살았습니다. 그러다 오늘 그 프로그램 작업을 하면서 로그가 올라오지 않는 문제에 대해서 집중 분석을 하게 되었습니다.

단계별로 모두 찍었는데 잘못되는 구간은 없었습니다. 그런데 유독 최종 결과물 페이지에서만 이상하게 나오는 현상을 발견했습니다. 페이지를 디버깅 하기를 수차례 … 결국 php가 무부호 정수를 지원하지 않는 사실을 깨닫게 되었습니다.

물론 무부호 정수를 지원하지 않는다는 사실에는 그럴 수 있다고 생각합니다. 그런데 참으로 안타까운 디자인 상의 에러는 (물론 전적으로 제 생각입니다.) , intval 함수가 범위를 넘어서는 정수 값이 입력으로 들어오는 경우에는 INT_MAX를 반환한다는 사실입니다. 즉, php에서 다음 코드를 수행하면 “2147483647 7fffffff”라는 결과를 얻게 됩니다.

$arg = intval('3000000000');
printf("%u %08x", $arg, $arg);

자 인제 코드를 다음과 같이 변경해 보겠습니다. 그러면 정상적인 “3000000000 b2d05e00″라는 결과를 볼 수 있습니다.

$arg = intval(3000000000);
printf("%u %08x", $arg, $arg);

이 무슨 안드로메다 같은 현상입니까? ㅠㅠ~ 결국 다음과 같은 택도 아닌 함수를 만들어서 값을 보정하는 수 밖에는 없었습니다. 물론 라운딩 되는 숫자들이 수많은 프로그램 버그를 양산 해온건 사실이지만, 그래도 이건 쫌 그렇네용. ㅋㅋ~

function d2i($s)
{
 $r = 0;
 $len = strlen($s);
 for($i=0; $i<$len; ++$i)
 {
  $r = $r * 10 + intval($s[$i]);
 }
 return $r;
}

물론 여기에 좀 더 엘레강스한 해결책이 있을지도 모르겠네요.

아시는 분은 제보해 주세요. ㅎㅎ~

@codemaru
돌아보니 좋은 날도 있었고, 나쁜 날도 있었다. 그런 나의 모든 소소한 일상과 배움을 기록한다. 여기에 기록된 모든 내용은 한 개인의 관점이고 의견이다. 내가 속한 조직과는 1도 상관이 없다.
(C) 2001 YoungJin Shin, 0일째 운영 중