헛.. 댓글이 수정/삭제가 안되는군요…(제가 못 찾는건지..)
윗 댓글에서 쓰고 싶었던 코드는
$arg = floatval(’3000000000′);
printf(”%u %08x”, $arg, $arg);
입니다. (3000000000에 따옴표가 빠졌네요.)
php와 unsigned int
by 신영진(YoungJin Shin), codewiz at gmail.com, @codemaru, http://www.jiniya.net
예전에 한 땐 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;
}
물론 여기에 좀 더 엘레강스한 해결책이 있을지도 모르겠네요.
아시는 분은 제보해 주세요. ㅎㅎ~
헛.. 댓글이 수정/삭제가 안되는군요…(제가 못 찾는건지..)
윗 댓글에서 쓰고 싶었던 코드는
$arg = floatval(’3000000000′);
printf(”%u %08x”, $arg, $arg);
입니다. (3000000000에 따옴표가 빠졌네요.)
$arg = d2i(’3000000000′);
var_dump($arg);
function d2i($s)
{
$r = 0;
$len = strlen($s);
for($i=0; $i<$len; ++$i)
{
$r = $r * 10 + intval($s[$i]);
}
return $r;
}
의 결과도 결국은..
float(3000000000)
그럼에도 불구하고 printf에 %u 옵션이 있는건 아이러니 하네요.
$arg = intval(3000000000);
var_dump($arg);
를 해보면 결과는
int(-1294967296) 입니다.
아마 C의 printf 호환성을 위해 있는게 아닐까 짐작을 해봅니다.
현의 노래 »
PHP가 unsigned int를 지원 하지 안는데 궂이 3000000000이라는 숫자를 int라고 생각해야 하는 이유가 무엇인지요?
PHP int의 범위를 벗어날 경우가 있는 경우라면 float으로 생각해야 하는게 맞는 것 같습니다만..
$arg = floatval(3000000000);
printf(“%u %08x”, $arg, $arg);