-992233736854775808은 PHPINT_아니 민.

11260 단어 PHPPHP_INT_MIN빈대

현상.


PHP_INT_MAX 및 PHPINT_MIN은 환경에 따라 달라진다. 예를 들어3v4lPHP_INT_MAX=9223372036854775807,PHP_INT_MIN=-9223372036854775808이다.
    var_dump(PHP_INT_MAX);
    var_dump(PHP_INT_MIN);

매뉴얼通常は PHP_INT_MIN === ~PHP_INT_MAX となる라고 쓰여 있다.
해보자. .
    var_dump(PHP_INT_MIN === ~PHP_INT_MAX);

진짜?
대단히 기쁘다.
여기서숫자와 비교하다해보세요.
    var_dump(PHP_INT_MAX, PHP_INT_MAX === 9223372036854775807);
    var_dump(PHP_INT_MIN, PHP_INT_MIN === -9223372036854775808);

어?PHP_INT_MIN === -9223372036854775808는 가짜다.
사실 PHPINT_MIN뿐만 아니라 수치 간 비교도 잘 모르는 일이 생길 수 있다.-9223372036854775807-1의 계산 결과가 정확하다-9223372036854775808, -9223372036854775808와 비교하면 false.
그러나-9223372036854775808피차간의 비교PHP_INT_MIN피차간의 비교true이었다.
무슨 일인지 모르겠다.
원인으로 말하자면 사실PHP_INT_MIN이라기보다는-9223372036854775808방면이다.
    var_dump(PHP_INT_MIN);
    var_dump(-9223372036854775808);

var_다만 덤프-9223372036854775808는 왠지float(-9.2233720368548E+18)로 바뀌었다.
PHP 계산INT_민에게서 빼면 맞다-9223372036854775808.그런데 그냥 빼면 플랫은 시원하다.
그나저나 이런 현상은 언제부터 일어났을까.
BUG표는 PHP4 시대부터 쭉표였지만 아무도 이 점을 눈치채지 못하고 놀랐다.
경계치의 테스트는2018/08/07에 제시일단인데 (int)존재라고 쓰여 있기 때문이다.
그리고 bug표는 var입니다.export의 원인인 것 같지만 실제로는 print, echo,sprintef 등에서도 발생할 수 있으니 수치 처리 문제를 고려해 보는 것이 좋다.

원인을 조사하다


여기서부터 아래쪽은 원본 파일을 비스듬히 읽었을 뿐 실제 디버깅한 것이 아니기 때문에 진짜인지 아닌지 장담할 수 없다.
조사에 사용된 버전은 PHP7입니다.2.8.===의 비교는 zend_operators.h감지되지 않음에서 진행되었다.
static zend_always_inline int fast_is_identical_function(zval *op1, zval *op2)
{
    if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) {
        return 0;
    } else if (Z_TYPE_P(op1) <= IS_TRUE) {
        return 1;
    }
    return zend_is_identical(op1, op2);
}
・유형에 따라 가짜를 회복합니다.
・ 만약 한 종류가 undefined/null/가짜/진짜라면 진짜로 돌아간다.
• 이외에도 젠드가 있습니다is_identical 결과를 되돌려줍니다.
zend_is_identical fast_is_identical_function 에서 정의합니다.
switch (Z_TYPE_P(op1)) {
    case IS_LONG:
        return (Z_LVAL_P(op1) == Z_LVAL_P(op2));
Z_LVAL_P는 long 값이 있는 매크로입니다.
비교 부분은 별다른 관계가 없는 것 같다.
그렇다면 도대체 어디가 문제일까? 사실 그 전에 나는 zend_operators.c 대본을 깨끗이 정리할 것이다.
다음은 수치 부분을 제거하는 발췌문입니다.
<ST_IN_SCRIPTING>{LNUM} {

    // 19桁未満なら
    if (yyleng < MAX_LENGTH_OF_LONG - 1) {
        // longにする
        ZVAL_LONG(zendlval, ZEND_STRTOL(yytext, &end, 0));

    // 19桁以上なら
    } else {
        // longにする
        ZVAL_LONG(zendlval, ZEND_STRTOL(yytext, &end, 0));

        // オーバーフローしていた
        if (errno == ERANGE) {
            // 1文字目が0だった
            if (yytext[0] == '0') {
                // 8進数からdoubleにする
                ZVAL_DOUBLE(zendlval, zend_oct_strtod(yytext, (const char **)&end));
            } else {
                // 10進数からdoubleにする
                ZVAL_DOUBLE(zendlval, zend_strtod(yytext, (const char **)&end));
            }
        }
    }
}
LNUM의 정의는 [0-9]+로 수치가 여기에 들어간다.- 입장하지 않습니다.
이 함수는 입력한 값ZVAL_LONG을 매크로로 롱형으로 만들지만 넘치면 더블 형으로 바꿉니다.
여기서부터 자구 해석 부근에 쓰고 싶지만, 최선을 다했으니 계속 써 주십시오.
한 마디로 하면 여기서 자구를 해석할 때-는 입력하지 않기 때문에 양과 음9223372036854775807을 막론하고 범위 내에서9223372036854775808는 넘침으로 판정된 것 같다.
따라서 -9223372036854775808 단어 해석이 끝날 때flat형으로 바뀌었다.-9223372036854775807-1 어휘 해석 시점92233720368547758071이 모두 범위 내에 있기 때문에 정상적으로 제거할 수 있다.
실제 응용에서는 (int)만 입력하면 되기 때문에 처리하는 것도 그리 대단한 일은 아니지만 근치를 위해 자구 해석은 반드시 손에 넣어야 하는 것이 비교적 심각하지 않습니까?

좋은 웹페이지 즐겨찾기